JFinal 一键生成表名,字段名等字段常量,告别复制粘贴!爽翻天!!!

使用 JFinal 自动生成数据库字段常量 —— 告别复制粘贴

使用 JFinal 自动生成数据库字段常量 —— 告别复制粘贴

在使用 JFinal 开发时,我们经常需要用到数据库表名和字段名,要么手动复制粘贴,要么定义常量,例如:

public interface UserFields {
    String USER_ID = "user_id";
    String USER_NAME = "user_name";
    String LOGIN_TIME = "login_time";
}

手动复制粘贴字段名、表名很难维护,一旦修改要大量改动代码;手动编写定义常量不仅繁琐,还容易出错——尤其是当字段名为 createTimeuser_ageYear 等混合命名时,常量名到底该写成 CREATE_TIME 还是 USER_AGE_YEAR?复制粘贴更是效率低下。

现在给你分享一个小技巧:借助 JFinal 的代码生成器(Generator) + Enjoy 模板,我们可以一键自动生成标准的大写下划线常量名!

✅ 支持任意命名风格

无论你的数据库字段是:

  • 标准下划线:session_key

  • 驼峰命名:userId

  • 混合风格:user_ageYeardevice_macAddress

都能自动转换为正确的常量名:

  • SESSION_KEY

  • USER_ID

  • USER_AGE_YEAR

  • DEVICE_MAC_ADDRESS

✅ 实现原理(JFinal代码生成器 + Enjoy 模板)

依赖:commons-lang3 3.18+,生成时间需要 hutool

在你的 base_model_template.jf 中加入以下模板代码:

javapackage #(baseModelPackageName);

import com.jfinal.plugin.activerecord.Model;
import com.jfinal.plugin.activerecord.IBean;

/**
 * Generated by JFinal, do not modify this file.
 * #(cn.hutool.core.date.DateUtil::format(cn.hutool.core.date.LocalDateTimeUtil::now(), "yyyy-MM-dd HH:mm:ss"))
 */
#if (generateChainSetter)
@SuppressWarnings({"serial", "unchecked"})
#else
@SuppressWarnings("serial")
#end
public abstract class #(tableMeta.baseModelName)<M extends #(tableMeta.baseModelName)<M>> extends Model<M> 
implements IBean {
	
	//>>>>>>>>>>>>>>>>加入以下代码<<<<<<<<<<<<<<<<<
	public interface #(tableMeta.modelName)Fields {
			
		/** Table */
		String TABLE_NAME = "#(tableMeta.name??)";
		#for(cm : tableMeta.columnMetas)
		#set(parts = cm.name.split("_"))
		#set(tokens = [])
		#for(part : parts)
		    #if(!part.isEmpty())
		    #set(camelParts = org.apache.commons.lang3.StringUtils::splitByCharacterTypeCamelCase(part))
		    #for(cp : camelParts)
		        #set(tokens.add(cp))
		    #end
		    #end
		#end
		#set(tokenArray = tokens.toArray())
		#set(snakeName = org.apache.commons.lang3.StringUtils::join(tokenArray, '_'))
		#set(upperSnake = snakeName.toUpperCase(java.util.Locale::ENGLISH))
		
		#if (cm.remarks)
		/** #(cm.name) : #(cm.remarks) */
		#end
		String #(upperSnake) = "#(cm.name)";
		#end
	}
	//>>>>>>>>>>>>>>>>加入以上代码<<<<<<<<<<<<<<<<<
	
#set(b = generateChainSetter)
#for(cm : tableMeta.columnMetas)
	#if (cm.remarks)
	/** #(cm.remarks) */
	 #end
	#set(argName = javaKeyword.contains(cm.attrName) ? '_' + cm.attrName : cm.attrName)
	public #(b ? 'M' : 'void') set#(firstCharToUpperCase(cm.attrName))(#(cm.javaType) #(argName)) {
		set("#(cm.name)", #(argName));
		#if (b)
		return (M)this;
		#end
	}
	
	#if (cm.remarks)
	/** #(cm.remarks) */
	 #end
	#set(getterOfModel = getterTypeMap.get(cm.javaType))
	#if (isBlank(getterOfModel))
		#set(getterOfModel = 'get')
	#end
	public #(cm.javaType) get#(firstCharToUpperCase(cm.attrName))() {
		return #(getterOfModel)("#(cm.name)");
	}

#end
}

在你的 model_template.jf 中加入以下模板代码(实现接口):

javapackage #(modelPackageName);

import #(baseModelPackageName).#(tableMeta.baseModelName);
import #(baseModelPackageName).#(tableMeta.baseModelName).#(tableMeta.modelName)Fields;  //添加

/**
 * Generated by JFinal, do not modify this file.
 * #(cn.hutool.core.date.DateUtil::format(cn.hutool.core.date.LocalDateTimeUtil::now(), "yyyy-MM-dd HH:mm:ss"))
 */
@SuppressWarnings("serial")
public class #(tableMeta.modelName) extends #(tableMeta.baseModelName)<#(tableMeta.modelName)> 
implements #(tableMeta.modelName)Fields { //添加实现代码
	#if(generateDaoInModel)
	public static final #(tableMeta.modelName) dao = new #(tableMeta.modelName)().dao();
	#end
}

💡 依赖说明:确保项目中已引入 commons-lang3 3.18+,生成时间需要 hutool

🚀 使用效果

运行 Generator 后,自动生成:

public abstract class BaseUser<M extends BaseUser<M>> extends Model<M> implements IBean {

	public interface UserFields {
		
		/** Table */
		String TABLE_NAME = "user";
		
		/** id */
		String ID = "id";
		
		/** lastLoginIp */
		String LAST_LOGIN_IP = "lastLoginIp";
		
		/** user_ageYear */
		String USER_AGE_YEAR = "user_ageYear";
	}
	
	/** ID */
	public M setId(java.lang.Long id) {
		set("id", id);
		return (M)this;
	}
	
	/** ID */
	public java.lang.Long getId() {
		return getLong("id");
	}
	
	...
}
public class User extends BaseUser<User> implements UserFields {
	
	public static final User dao = new User().dao();
	
}

无需手动处理命名转换,彻底告别复制粘贴!

✅ 直接使用常量

然后你就可以在你需要的地方直接使用 类名.属性名

System.out.println(User.TABLE_NAME);
System.out.println(User.ID);
System.out.println(User.LAST_LOGIN_IP);
System.out.println(User.USER_AGE_YEAR);

✅ 优势总结

  • 全自动:建完表,跑一次 Generator 即可

  • 智能转换:正确处理驼峰、下划线、混合命名

  • 零维护:表结构变更后重新生成即可同步,哪里引用出错一眼便能看到

  • 类型安全:常量名与字段名严格一致,避免拼写错误

📌 小贴士

若项目未启用静态方法调用,需在 configEngine 中添加(jfinal代码生成器已自动加入,你自己写的要手动加入):

me.setStaticFieldExpression(true); //开启静态属性访问
me.setStaticMethodExpression(true); //开启静态方法调用

从此,字段常量自动生成,调用更是简单,只需 类名.属性名,开发效率翻倍!
 JFinal 不仅快,还能让你写更少的代码,做更多的事。

评论区

JFinal

2025-12-30 22:01

这个生成 interface UserFields 的方式是没见过的创新。

我在 aifei-db 中是先创建了一个 Table 类,然后生成了针对它的初始化:
public static final Table TABLE = new Table(
"user",
"id",
new String[]{"id"},
User.class,
new HashMap>() {{
put("id", Integer.class);
}}
);

思路差不多,省去了启动时对数据库的读取与反射,启动速度仅为 300 毫秒。

热门分享

扫码入社