如何将枚举值存入数据库并避免枚举与SQL语句重复编写?
枚举存储重复编码问题解决方案
以下方案都可以实现只维护枚举类代码,无需重复编写SQL插入语句:
方案1:应用启动时自动同步枚举值到Lookup表
这是落地成本最低、最常用的方案,实现逻辑如下:- 先给
Lookup接口定义统一的取值方法,所有业务枚举实现该接口,对外暴露id、code、名称、描述等字段的get方法;同时自定义一个@LookupGroup注解,标记在枚举类上,指定当前枚举对应的groupId、groupName参数:
// 分组标记注解 @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface LookupGroup { int groupId(); String groupName(); } // 枚举类加上注解 @LookupGroup(groupId = 23, groupName = "JOB_TRACKING_TYPE") public enum EJobTrackingType implements Lookup<EJobTrackingType> { NOTIFY_SERVICE(230000001, 1,"Notify service", "desc"), COMPLETED_SERVICE(230000002, 2,"Completed service", "desc"), // 其余上百个枚举值 }- 写一段启动执行的逻辑(如果是Spring项目可以实现
ApplicationRunner接口,或者用@PostConstruct注解),启动时扫描指定包路径下所有带@LookupGroup注解的枚举类,通过反射读取每个枚举实例的字段值,自动和TBL_LOOKUP表的存量数据做对比:不存在对应id的记录就执行插入,存在但字段值有变动就执行更新,还可以根据业务需要把分组下枚举里已经删除的存量记录标记为失效。
这个方案完全不需要手写任何插入SQL,后续新增、修改枚举值只需要改枚举类代码,重启应用就会自动同步到数据库,从根源上避免两边值不一致的问题。
- 先给
方案2:编译期自动生成初始化SQL脚本
如果团队流程要求必须通过静态SQL脚本做数据初始化(比如DBA要求所有库表变更必须走SQL审核,不允许应用直接操作Lookup表数据),可以自定义Java注解处理器,在项目编译阶段扫描所有标记了@LookupGroup的枚举类,自动拼接生成对应的insert初始化SQL文件,打包构建时直接把生成的SQL纳入版本管理即可。
这个方案不需要运行时做反射扫描,也不需要改应用启动逻辑,改完枚举重新编译就会自动更新SQL内容,同样不需要手动编写上百条重复插入语句。方案3:简化Lookup表逻辑,直接用ORM框架的枚举映射能力
如果Lookup表没有给外部系统提供配置查询、下拉选项这类强需求,只是为了在业务表关联枚举值,可以直接去掉手动维护Lookup表的逻辑,用MyBatis-Plus、JPA这类ORM框架自带的枚举映射能力,配置枚举按指定的id/code字段和数据库字段做转换,业务数据存取时框架会自动完成枚举实例和数据库值的映射,连Lookup表的维护成本都可以省掉。
注意事项:所有方案都要求给每个枚举实例配置固定的id值(就像你当前代码里写的230000001这类固定值),不要用枚举默认的
ordinal()顺序值作为存储id,避免后续调整枚举顺序、新增枚举时id错乱,导致历史关联数据出错。
内容的提问来源于stack exchange,提问作者Ranjithkumar
相关产品推荐
相关产品推荐

