枚举类虽然很简单,但是却往往是系统中业务逻辑最集中最复杂的地方。本文将会分享我们项目中基于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. Django中的枚举类型

    一.枚举类型示例 枚举类型可以看作是一种标签或是一系列常量的集合,通常用于表示某些特定的有限集合,例如星期.月份.状态等.Python 的原生类型(Built-in types)里并没有专门的枚举类型 ...

  2. Java虚拟机14:Java对象大小、对象内存布局及锁状态变化

    一个对象占多少字节? 关于对象的大小,对于C/C++来说,都是有sizeof函数可以直接获取的,但是Java似乎没有这样的方法.不过还好,在JDK1.5之后引入了Instrumentation类,这个 ...

  3. Bash提示符

    Bash有四种提示符 1.基本提示符(PS1):即$符号,是默认的基本提示符,当Shell运行在交互模式下时,该提示符会出现在屏幕上,可以设置为其它符号. 显示PS1设置[cb@cb:16:36:23 ...

  4. none 和 host 网络的适用场景 - 每天5分钟玩转 Docker 容器技术(31)

    本章开始讨论 Docker 网络. 我们会首先学习 Docker 提供的几种原生网络,以及如何创建自定义网络.然后探讨容器之间如何通信,以及容器与外界如何交互. Docker 网络从覆盖范围可分为单个 ...

  5. webpack 实现的多入口项目脚手架

    简介 基于 webpack2 实现的多入口项目脚手架,主要使用 extract-text-webpack-plugin 实现 js .css 公共代码提取,html-webpack-plugin 实现 ...

  6. 浅谈Cordova框架的一些理解

    前言 因为工作原因,最近需要研究Cordova框架,看了其中的源码和实现方式,当场在看的时候马上能理解,但是事后再回去看相关源码时候却发现之前理解的内容又忘记了,又不得不重新开始看,所以总觉得需要记录 ...

  7. Java注解--实现简单读取excel

    实现工具类 利用注解实现简单的excel数据读取,利用注解对类的属性和excel中的表头映射,使用Apache的poi就不用在业务代码中涉及row,rows这些属性了. 定义注解: @Retentio ...

  8. 【LeetCode】233. Number of Digit One

    题目: Given an integer n, count the total number of digit 1 appearing in all non-negative integers les ...

  9. 【Android Developers Training】 80. 管理网络使用

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

  10. Python 实现 Discuz论坛附件下载权限绕过漏洞

    背景:最近压力有些大,想玩点游戏放松下,去Mac论坛下载,发现需要各种权限,于是蛋疼了. 所以,上网查了discuz! x3.1破解,手动替换,发现出现“链接已过期”.所以写了下面程序. 0.将下列代 ...