枚举类虽然很简单,但是却往往是系统中业务逻辑最集中最复杂的地方。本文将会分享我们项目中基于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 使用枚举字段的最佳实践的更多相关文章

  1. Jira字段配置最佳实践

    在我们创建Jira时,Jira上会填写各式各样的字段,不同的字段对于不同的角色人员,使用方式也是不同的,通过这篇文章,希望大家能够对Jira使用有更深刻的认识. 为什么需要严格规范? 易于开发,测试, ...

  2. atitit. 统计功能框架的最佳实践(1)---- on hibernate criteria

    atitit. 统计功能框架的最佳实践(1)---- on hibernate criteria 1. 关键字 1 2. 统计功能框架普通有有些条件选项...一个日期选项..一个日期类型(日,周,月份 ...

  3. Struts2、Spring、Hibernate 高效开发的最佳实践(转载)

    Struts2.Spring.Hibernate 高效开发的最佳实践 Struts2.Spring.Hibernate(SSH)是最常用的 Java EE Web 组件层的开发技术搭配,网络中和许多 ...

  4. hibernate 多对多 最佳实践

    首先 看看我们 ER 画画 :盖  一对一 .一对多 .多对多 的关系 watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvem91dG9uZ3l1YW4=/fo ...

  5. 【GoLang】golang 最佳实践汇总

    最佳实践 1 包管理 1.1 使用包管理对Golang项目进行管理,如:godep/vendor等工具 1.2 main/init函数使用,init函数参考python 1.2.1 main-> ...

  6. MySQL 性能优化 30个数据库设计的最佳实践

    数据库设计是整个程序的重点之一,为了支持相关程序运行,最佳的数据库设计往往不可能一蹴而就,只能反复探寻并逐步求精,这是一个复杂的过程,也是规划和结构化数据库中的数据对象以及这些数据对象之间关系的过程. ...

  7. Google Developing for Android 二 - Memory 最佳实践 // lightSky‘Blog

    Google Developing for Android 二 - Memory 最佳实践   |   分类于 Android最佳实践 原文:Developing for Android, II Th ...

  8. JSR 303 - Bean Validation 介绍及最佳实践

    JSR 303 - Bean Validation 介绍及最佳实践 JSR 303 – Bean Validation 是一个数据验证的规范,2009 年 11 月确定最终方案.2009 年 12 月 ...

  9. atitit.hbnt orm db 新新增更新最佳实践o99

    atitit.hbnt orm db 新新增更新最佳实践o99 1. merge跟个save了. 1 2. POJO对象处于游离态.持久态.托管态.使用merge()的情况. 1 3. @Dynami ...

随机推荐

  1. 《物联网框架ServerSuperIO教程》-21.终端控制传感器或设备,形成回路控制。附:demo源代码

    21.1     概述 ServerSuperIO以前所做的工作逐步为形成回路控制或级联控制打下基础,例如:服务连接器和设备驱动连接器的开发与应用.总之,是通过多种形式下发命令控制设备(驱动)或传感器 ...

  2. 对于JSONObject,我只是临时抱佛脚

    说起JSON,大家就谈不上陌生了,因为对于数据传输语言,各位只认json,即使有XML语言,但是各位很少用吧.我也是,但是之前用过的json转换工具各种各样,我记忆中有过GSON(google).fa ...

  3. 使用requireJs的方法

    在你们对requireJs初步了解后,快来看看他们是怎么使用的吧. 在你下载完成require.js插件后,在页面里引入,在require.js 加载完之后,会查找页面上script标签的data-m ...

  4. iOS内购图文流程(2017)

    什么是内购? 只要在iPhone App上购买的不是实物产品(也就是虚拟产品如qq币.虎牙币.电子书......) 都需要走内购流程,苹果这里面抽走三成.   使用内购需要走的流程. 1,填写协议,税 ...

  5. 学容器必须懂 bridge 网络 - 每天5分钟玩转 Docker 容器技术(32)

    上一节我们讨论了 none 和 host 类型的容器网络,本节学习应用最广泛也是默认的 bridge 网络. Docker 安装时会创建一个 命名为 docker0 的 linux bridge.如果 ...

  6. ci框架中表前缀的处理

    后面的写死,前面的无论如何改变都没事,会自动的替换,以后如果数据库的表前缀被修改了,只需要修改上面的配置项,下面的不变

  7. 【Android Developers Training】 95. 创建一个同步适配器

    注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...

  8. Java编码问题汇总

    转自 http://www.blogjava.net/zhangchao/archive/2011/05/26/351051.html Thanks Java编码问题汇总 工作中经常遇到java编码问 ...

  9. 探索Windows命令行系列(7):通过命令编译C#类和Java类

    1.编译 C# 类 1.1.C# 编译工具 1.2.编译一个 C# 类 1.3.编译多个 C# 类 2.编译 Java 类 2.1.Java 编译工具 2.2.编译 Java 类 3.组合命令符 4. ...

  10. js实现类似iphone的秒表-添加平均数功能

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name ...