hibernate 使用枚举字段的最佳实践
枚举类虽然很简单,但是却往往是系统中业务逻辑最集中最复杂的地方。本文将会分享我们项目中基于hibernate的枚举类使用规范,包含数据库中枚举列数据类型、注释、枚举列与枚举类的映射等。
一、枚举类定义规范
package org.jframe.data.enums; /**
* Created by leo on 2017-05-31.
*/
public enum Gender {
unknown(0),
male(11),
female(12); public final static String Doc = "0: unknown; 11: male; 12: female"; private final int value;
private Gender(int value){
this.value = value;
} public int getValue(){
return this.value;
} }
请注意,枚举类一定要包含一个常量字符串用于说明每一个枚举值的作用。为什么一定要放在枚举类里面?那是因为每当枚举值有改变的的时候,能够不用想都知道修改这个说明文档。这个说明文档在哪些地方用到呢?1: 数据库定义(见下文);2:swagger API自动文档。
二、数据库定义
@Column(name = "gender", columnDefinition = "int not null COMMENT '" + Gender.Doc + "'")
@Convert(converter = GenderConverter.class)
private Gender gender;
上一步定义的枚举类说明,在这里的columnDefinition就用到了。这样,如果使用code first模式生成数据库,那么数据库中该列就会包含该枚举类的说明文档了。这也是我们强烈建议使用code first模式的重要原因。
最大的好处:使用强类型的枚举类而不是string或int类型。
关于数据库定义,有几个为什么需要解释一下。
1. 为什么使用int类型而非@Enumerated(EnumType.STRING)?答:java代码中的枚举类的成员随时可能会改变,比如之前拼写错误需要重构,或者就是任何理由的重构,虽然代码改了,但是数据库中已经存在的记录还是使用原来的枚举值,这就非常危险了。所以,使用EnumType.STRING是极其危险的,因为你改了代码而没有任何地方通知你去改老数据,这对于新手程序员来讲就很容易写出危险的代码了,这就不是一个好的架构师该做的架构了。
2. 为什么一定要是使用AttributeConverter?答:如果不使用这个converter,hibernate默认会根据java代码中枚举成员出现的顺序的index作为存到数据库中的值。这就极其危险了。因为我们很有可能重构代码调整枚举成员顺序,或者插入新的成员,但是数据库中已经存在的记录还是原来的顺序值。所以,不使用attributeconverter是极其危险的,因为你改了代码而没有任何地方通知你去改老数据,这对于新手程序员来讲就很容易写出危险的代码了,这就不是一个好的架构师该做的架构了。
三、AttributeConverter
package org.jframe.data.converters; import org.jframe.data.enums.Gender;
import org.jframe.infrastructure.core.JList; import javax.persistence.AttributeConverter; /**
* Created by leo on 2017-06-28.
*/
public class GenderConverter implements AttributeConverter<Gender, Integer> {
@Override
public Integer convertToDatabaseColumn(Gender gender) {
return gender.getValue();
} @Override
public Gender convertToEntityAttribute(Integer integer) {
return JList.from(Gender.values()).firstOrNull(x -> x.getValue() == integer);
}
}
这就很简单了,无需赘述。
四、心得
相比于.NET体系下面的entity framework,可以看到hibernate的架构师给程序员挖了两个坑。使用entity framework,即便是初级程序员也很难因为改了枚举类代码导致数据库的数据错误,但是使用hibernate就不一样了,即便是很多中高级程序员,也很容易因为改了枚举类代码而导致数据库中的数据错误。
所以,我们项目中就建立了上面所描述的规范,如果没有这个规范,程序员就很容易因为改了代码而忘记改数据库导致严重数据错误。
本文中的代码来自jframe 框架
基于spring mvc搭建的多层级多模块java web应用程序框架。包含:基础设施层、数据库定义规范、数据库访问规范、日志记录规范、多层级异常捕获、标准ajax规范、母版页规范、视图呈现规范、JavaScript框架规范等。实际上该框架定义的规范极其详细,比如数据库定义层:枚举类使用规范、datetime/bool/string字段规范、1对1、1对多、多对1、多对多外键关系映射规范、父类定义规范、字段注释规范、懒加载规范等等。。。
jframe github地址: https://github.com/leotsai/jframe,技术交流QQ群:651499479,欢迎java大神加群,也欢迎新手进群学习。
如果你们项目中有更好的枚举类使用经验,请一定要分享出来哦!
THE END
hibernate 使用枚举字段的最佳实践的更多相关文章
- Jira字段配置最佳实践
在我们创建Jira时,Jira上会填写各式各样的字段,不同的字段对于不同的角色人员,使用方式也是不同的,通过这篇文章,希望大家能够对Jira使用有更深刻的认识. 为什么需要严格规范? 易于开发,测试, ...
- atitit. 统计功能框架的最佳实践(1)---- on hibernate criteria
atitit. 统计功能框架的最佳实践(1)---- on hibernate criteria 1. 关键字 1 2. 统计功能框架普通有有些条件选项...一个日期选项..一个日期类型(日,周,月份 ...
- Struts2、Spring、Hibernate 高效开发的最佳实践(转载)
Struts2.Spring.Hibernate 高效开发的最佳实践 Struts2.Spring.Hibernate(SSH)是最常用的 Java EE Web 组件层的开发技术搭配,网络中和许多 ...
- hibernate 多对多 最佳实践
首先 看看我们 ER 画画 :盖 一对一 .一对多 .多对多 的关系 watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvem91dG9uZ3l1YW4=/fo ...
- 【GoLang】golang 最佳实践汇总
最佳实践 1 包管理 1.1 使用包管理对Golang项目进行管理,如:godep/vendor等工具 1.2 main/init函数使用,init函数参考python 1.2.1 main-> ...
- MySQL 性能优化 30个数据库设计的最佳实践
数据库设计是整个程序的重点之一,为了支持相关程序运行,最佳的数据库设计往往不可能一蹴而就,只能反复探寻并逐步求精,这是一个复杂的过程,也是规划和结构化数据库中的数据对象以及这些数据对象之间关系的过程. ...
- Google Developing for Android 二 - Memory 最佳实践 // lightSky‘Blog
Google Developing for Android 二 - Memory 最佳实践 | 分类于 Android最佳实践 原文:Developing for Android, II Th ...
- JSR 303 - Bean Validation 介绍及最佳实践
JSR 303 - Bean Validation 介绍及最佳实践 JSR 303 – Bean Validation 是一个数据验证的规范,2009 年 11 月确定最终方案.2009 年 12 月 ...
- atitit.hbnt orm db 新新增更新最佳实践o99
atitit.hbnt orm db 新新增更新最佳实践o99 1. merge跟个save了. 1 2. POJO对象处于游离态.持久态.托管态.使用merge()的情况. 1 3. @Dynami ...
随机推荐
- Java代码实现 增删查 + 分页——实习第四天
今天项目内容已经开始了,并且已经完成好多基本操作,今天就开始总结今天学习到的内容,和我遇到的问题,以及分析这其中的原因. 内容模块: 1:Java代码实现对数据库的增删查: 2:分页且获取页面信息: ...
- 使用File、Path和Directory进行常见的操作
我们偶尔会用到文件操作,其中File.Path和Directory这三个类是比较常见的,今天写了一个测试demo,也是顺便学习一下,记录一二. BTW,使用这几个类的时候需要引用using Syste ...
- 远程调用其它站点并设置cookie
远程调用其它站点并设置cookie: 参考js var domainArray = [ {site:'g.com',action:'/b.do?c' } ,{site:'www.baidu.com', ...
- tcpdf导出pdf数据支持中文的解决方案
步骤如下:1.确保你测试tcpdf能正常输出英文内容的pdf2.测试输入中文内容后显示是?的乱码或者空白分析原因,是因为我们输入的中文,tcpdf字体库并不支持,因此乱码或者空白显示 添加一个合适的字 ...
- abelkhan编译文档
abelkhan github:https://github.com/qianqians/abelkhan abelkhan编译文档 在编译abelkhan之前,需要先编译第三方库boost.libb ...
- input 等替换元素的baseline问题
行内标签和设置为block:inline;形式的标签与input并排放置时,为何会错位?例如下面的. 因为在同一行中,所有行内元素默认 baseline 对齐.但是,input(还有textarea. ...
- JQuery事件机制笔记
一.事件绑定及移除 1.bind() bind()为每个匹配的元素绑定一个或多个事件处理函数: 语法:bind(event,fn)//不能给未来元素添加事件: bind(event,fn); bind ...
- JAVA基础——面向对象三大特性:封装、继承、多态
JAVA面向对象三大特性详解 一.封装 1.概念: 将类的某些信息隐藏在类内部,不允许外部程序直接访问,而是通过该类提供的方法来实现对隐藏信息的操作和访问. 2.好处: 只能通过规定的方法访问数据. ...
- 详解Mysql自动备份与恢复
通过 mysqldump命令,直接生成一个完整的 .sql 文件 Step 1: 创建一个批处理备份SQL c: cd C:Program Filesmysql5.6.24bin mysqldump ...
- 关于一点jeesite
最近刚接触jeesite 深深被这个功能强大的框架所折服,虽然其中有一些地方还不完善,但也不妨碍我们通过jeesite提高我们java水平的大门. 这两天在网上一直在找关于jeesite的文章,看来看 ...