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 ...
随机推荐
- 关于URL的理解
引言 URL,是统一资源定位符(Uniform Resource Locator)的缩写,一个URL就是一个特定资源在网络上的地址.理论上讲,一个URL指向一个唯一的资源,这个资源可以使一个HTML页 ...
- jsp,jquery,spring mvc 实现导出文件
需求:在界面上选择一个日期,然后点击导出按钮,直接导出选择月份的考勤excel文件. 这篇文章主要是介绍如何下载文件! jsp中代码: <div class="form-group&q ...
- python入门小记
一.help python中的帮助手册,对于初学者,多多使用help,多看看原生注释-- 1.help的使用 1.命令需要使用双引号或者单引号括起来,不使用引号引起来会报错 2.类或者函数(方法)不需 ...
- 从netty源码里拿到的关于http错误码,自己学习下
public static HttpResponseStatus valueOf(int code) { switch (code) { case 100: return CONTINUE; case ...
- 在vue 中使用Stylus
概述 什么是Stylus Stylus是一个CSS预处理器. 什么是CSS预处理器 关于CSS预处理器,推荐先行阅读这篇文章:为您详细比较三个 CSS 预处理器(框架):Sass.LESS 和 Sty ...
- kubeadm 安装1.6.0版本出错 未解决
工具包已经安装好了. [root@master data]# rpm -qa |grep kubekubeadm-1.6.0-0.x86_64kubectl-1.6.0-0.x86_64kubelet ...
- Windows 10环境安装VIM代码补全插件YouCompleteMe
Windows 10环境安装VIM代码补全插件YouCompleteMe 折腾一周也没搞定Windows下安装VIM代码补全插件YouCompleteMe,今天在家折腾一天总算搞定了.关键问题是在于P ...
- 两种代理模式(JDK和Cglib)实例
CGlib代理模式: package CGLIB; import java.lang.reflect.Method; import JDK.Test; import net.sf.cglib.prox ...
- [leetcode-474-Ones and Zeroes]
In the computer world, use restricted resource you have to generate maximum benefit is what we alway ...
- 【LeetCode】306. Additive Number
题目: Additive number is a string whose digits can form additive sequence. A valid additive sequence s ...