Hibernate中枚举Enum类型的映射策略
2017-05-16 16:04
435 查看
在Java中
注意本文使用的数据库是MySQL5.7,版本和数据库类型可能会有不同的结果。
首先我们要明确的是将Enum类型的字段映射到数据库中有两种方式:
一个是通过使用Enum类型实例在Enum中声明的顺序,也就是
一个是通过使用Enum类型实例中的
这两个属性其实都在
当不使用任何注解的时候,默认情况下是使用
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
这里Gender就是我们的Enum类,如下:
2
3
4
5
6
7
8
9
10
11
12
13
1
2
3
4
5
6
7
8
9
10
11
12
13
此时看到生成的表结构如下:
这里可以看出Enum类型字段Gender**被映射成int(11)类型**,通过往里面插入一条数据看一下结果,如下:
2
3
4
5
1
2
3
4
5
上边向数据库中插入了两条记录,personService是操作数据库的service,结果如下:
可以看出Gender.male对应的序号是0,Gender.female对应的是1,可以看出在使用
注解
Specifies that a persistent property or field should be persisted as a enumerated type. The
used in conjunction with the Basic annotation, or in conjunction with the
collection value is of basic type. If the enumerated type is not specified or the Enumerated annotation is not used, the
is assumed to be ORDINAL.
如果不使用该注解,就是在上面说的默认的情况是使用Enum中的
主要说明一下将Enum类型映射成字符串的方式,其实只是将Enum类型上的注解改为
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
此时看到生成的表结构如下:
这里可以看出Enum类型字段Gender**被映射成VARCHAR(255)类型**,通过往里面插入一条数据看一下结果,如下:
2
3
4
5
1
2
3
4
5
可以看出是插入的对应Enum类型的name属性,就是这么简单!
关于
X 是实体属性的类型
Y 是数据库字段的类型
Y convertToDatabaseColumn(X) 作用:将实体属性X转化为Y存储到数据库中,即插入和更新操作时执行;
X convertToEntityAttribute(Y) 作用:将数据库中的字段Y转化为实体属性X,即查询操作时执行;
使用
2
3
4
5
6
7
8
9
10
11
12
13
1
2
3
4
5
6
7
8
9
10
11
12
13
所有的属性转换器需要实现AttributeConverter接口,这个接口可以将实体中的数据转换成到数据库中存储,这种方式可以用来映射实体属性,也可以用来将实体中数据加密存储到数据库中,这个转换器还需要使用
下面要重写我们的Gender枚举类,如下:
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
下面使用这个转换器如下:
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
生成的数据库结构如下:
可以看出和使用
2
3
4
5
1
2
3
4
5
结果如下:
可以看出插进去的数据已经不是Enum实例的name属性值了,而是我们自定义的value值。
Enum是一种“奇葩”的存在,“奇葩”不代表没用,对于这种比较特殊的存在,hibernate会有很多种选择来完成Enum类型字段的映射,首先要说明的是在hibernate都是把
Enum类型的字段映射成基本类型的字段,并且我这里不使用任何配置文件来配置映射,而是统一使用注解这种方式来完成映射。
注意本文使用的数据库是MySQL5.7,版本和数据库类型可能会有不同的结果。
首先我们要明确的是将Enum类型的字段映射到数据库中有两种方式:
一个是通过使用Enum类型实例在Enum中声明的顺序,也就是
ordinal属性,通过这个序号来将Enum类型字段映射成int类型来存储;
一个是通过使用Enum类型实例中的
name属性来完成映射,这里讲Enum类型映射成String类型来完成存储;
这两个属性其实都在
java.lang.Enum中,这个类是所有Enum类型的父类。
1. 不使用任何注解
当不使用任何注解的时候,默认情况下是使用ordinal属性,也就是Enum类型实例在Enum中声明的顺序来完成映射的,具体情况如下:
@Entity public class Person implements Serializable{ private static final long serialVersionUID = 8849870114127659929L; @Id @GeneratedValue private Long id; @Column(nullable = false) private String name; @Column private Gender gender; public Person(String name, Gender gender){ this.name = name; this.gender = gender; } // getter、setter }1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
这里Gender就是我们的Enum类,如下:
public enum Gender { male("男"), female("女"); private String name; private Gender(String name){ this.name = name; } public String getName(){ return this.name; } }1
2
3
4
5
6
7
8
9
10
11
12
13
1
2
3
4
5
6
7
8
9
10
11
12
13
此时看到生成的表结构如下:
这里可以看出Enum类型字段Gender**被映射成int(11)类型**,通过往里面插入一条数据看一下结果,如下:
@Test public void testJpa(){ personService.save(new Person("Jhon", Gender.male)); personService.save(new Person("Lily", Gender.female)); }1
2
3
4
5
1
2
3
4
5
上边向数据库中插入了两条记录,personService是操作数据库的service,结果如下:
可以看出Gender.male对应的序号是0,Gender.female对应的是1,可以看出在使用
ordinal属性映射时的序号是从0开始的。
2. 使用@Enumerated
注解
注解javax.persistence.Enumerated从名字上来看就可以明白是为了映射Enum类型的,从它的javadoc文档中可以说明:
Specifies that a persistent property or field should be persisted as a enumerated type. The
Enumeratedannotation may be
used in conjunction with the Basic annotation, or in conjunction with the
ElementCollectionannotation when the element
collection value is of basic type. If the enumerated type is not specified or the Enumerated annotation is not used, the
EnumTypevalue
is assumed to be ORDINAL.
如果不使用该注解,就是在上面说的默认的情况是使用Enum中的
ordinal属性来完成,所以关于这部分就不详细阐述了。
主要说明一下将Enum类型映射成字符串的方式,其实只是将Enum类型上的注解改为
@Enumerated(EnumType.STRING)即可,如下:
@Entity public class Person implements Serializable{ private static final long serialVersionUID = 8849870114127659929L; @Id @GeneratedValue private Long id; @Column(nullable = false) private String name; @Column @Enumerated(EnumType.STRING) private Gender gender; public Person(String name, Gender gender){ this.name = name; this.gender = gender; } // getter、setter }1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
此时看到生成的表结构如下:
这里可以看出Enum类型字段Gender**被映射成VARCHAR(255)类型**,通过往里面插入一条数据看一下结果,如下:
@Test public void testJpa(){ personService.save(new Person("Jhon", Gender.male)); personService.save(new Person("Lily", Gender.female)); }1
2
3
4
5
1
2
3
4
5
可以看出是插入的对应Enum类型的name属性,就是这么简单!
3. 使用AttributeConverter
属性类型转换器
关于AttributeConverter<X, Y>
X 是实体属性的类型
Y 是数据库字段的类型
Y convertToDatabaseColumn(X) 作用:将实体属性X转化为Y存储到数据库中,即插入和更新操作时执行;
X convertToEntityAttribute(Y) 作用:将数据库中的字段Y转化为实体属性X,即查询操作时执行;
使用
AttributeConverter可以将Enum中的属性名转换成数据库中存储的字段名,定义一个属性转换器如下:
@Converter public class GenderConverter implements AttributeConverter<Gender, String> { @Override public String convertToDatabaseColumn(Gender attribute) { return attribute.getValue(); } @Override public Gender convertToEntityAttribute(String dbData) { return Gender.fromString(dbData); } }1
2
3
4
5
6
7
8
9
10
11
12
13
1
2
3
4
5
6
7
8
9
10
11
12
13
所有的属性转换器需要实现AttributeConverter接口,这个接口可以将实体中的数据转换成到数据库中存储,这种方式可以用来映射实体属性,也可以用来将实体中数据加密存储到数据库中,这个转换器还需要使用
@Converter注解标识出来。
下面要重写我们的Gender枚举类,如下:
public enum Gender { male("男"), female("女"); private String value; private Gender(String value){ this.value = value; } public String getValue(){ return this.value; } public static Gender fromString(String value){ Objects.requireNonNull(value, "value can not be null"); Gender gender = null; if("男".equals(value)){ gender = male; } else if("女".equals(value)){ gender = female; } return gender; } }1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
下面使用这个转换器如下:
@Entity public class Person implements Serializable{ private static final long serialVersionUID = 8849870114127659929L; @Id @GeneratedValue private Long id; @Column(nullable = false) private String name; @Column @Convert(converter = GenderConverter.class) private Gender gender; public Person(String name, Gender gender){ this.name = name; this.gender = gender; } // getter、setter }1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
生成的数据库结构如下:
可以看出和使用
@Enumerated(EnumType.STRING)生成的类型是相同的,但是别急,看看插入的数据是怎么样的?
@Test public void testJpa(){ personService.save(new Person("Jhon", Gender.male)); personService.save(new Person("Lily", Gender.female)); }1
2
3
4
5
1
2
3
4
5
结果如下:
可以看出插进去的数据已经不是Enum实例的name属性值了,而是我们自定义的value值。
相关文章推荐
- Hibernate中枚举Enum类型的映射策略
- Hibernate 映射枚举(Enum) 类型的属性
- Hibernate将Enum枚举类型映射为Int类型
- Hibernate将Enum枚举类型映射为Int类型(补充VARCHAR类型配置)
- Hibernate枚举类型数据库映射方案
- * hibernate3 自定义枚举映射类型
- Hibernate-Java-SQL 类型映射表 及Hibernate标识生成策略
- Hibernate中日期类型字段的映射策略
- Hibernate 主键维护策略和hibernate 常见的映射类型
- JAVA-Hibernate-SQL类型映射表及Hibernate标识生成策略
- Hibernate--Enum类型的set集合映射到数据库(xml配置文件实现方式)
- [原创]java WEB学习笔记81:Hibernate学习之路--- 对象关系映射文件(.hbm.xml):hibernate-mapping 节点,class节点,id节点(主键生成策略),property节点,在hibernate 中 java类型 与sql类型之间的对应关系,Java 时间和日期类型的映射,Java 大对象类型 的 映射 (了解),映射组成关系
- Hibernate针对Java基本类型字段的映射策略总结
- hibernate将enum映射成int或varchar类型
- JDK5.0新特性:枚举类型enum、枚举集合EnumSet、枚举映射EnumMap
- jackson 枚举 enum json 解析类型 返回数字 或者自定义文字
- Hibernate对象映射类型
- Hibernate-2映射 Java 的时间, 日期类型
- C# 枚举类型 enum
- hibernate中Map类型的双向一对多映射