对于枚举类型,不能通过org.hibernate.annotations.Type注解来简单的映射对应的数据库字段类型(除非自定义类型)。对此,Hibernate提供了javax.persistence.Enumerated注解,该注解的参数有两种场景:
1.EnumType.STRING:使用该参数时,数据库表中会存储枚举的字符串值;
2.EnumType.ORDINAL:使用该参数时,数据库表中存在的是枚举的int型值;
假如在数据类Movie.java中新增一个type字段,该字段被定义为枚举类型MovieType,用于标识该影视是电影、电视剧还是动漫。枚举MovieType代码如下:
1 packagestudy.hibernate.model;2
3 public enumMovieType {4 FILM,5
6 TV,7
8 CARTOON,9
10 VARIETY11 }
在数据类中对type属性添加@Enumerated注解来配置映射关系:
1 packagestudy.hibernate.model;2
3 importjavax.persistence.Column;4 importjavax.persistence.Convert;5 importjavax.persistence.Entity;6 importjavax.persistence.EnumType;7 importjavax.persistence.Enumerated;8 importjavax.persistence.Id;9 importjavax.persistence.Table;10
11 importorg.hibernate.annotations.Type;12
13 /**
14 * 电影数据类15 *16 */
17 @Entity18 @Table(name="MOVIE")19 public classMovie {20 @Id21 @Column(name="MOVIE_ID")22 private intid;23
24 @Column(name="NAME")25 @Type(type="string")26 privateString name;27
28 @Column(name="DESCRIPTION")29 @Type(type="text")30 privateString description;31
32 @Column(name="TYPE")33 @Enumerated(EnumType.ORDINAL)34 privateMovieType type;35
36 public intgetId() {37 returnid;38 }39
40 public void setId(intid) {41 this.id =id;42 }43
44 publicString getName() {45 returnname;46 }47
48 public voidsetName(String name) {49 this.name =name;50 }51
52 publicString getDescription() {53 returndescription;54 }55
56 public voidsetDescription(String description) {57 this.description =description;58 }59
60 publicMovieType getType() {61 returntype;62 }63
64 public voidsetType(MovieType type) {65 this.type =type;66 }67
68 }
在应用启动时,设置对应的type属性:
Movie movie = newMovie();
movie.setId(1);
movie.setName("速度与激情8");
movie.setDescription("多米尼克(范·迪塞尔 Vin Diesel 饰)与莱蒂(米歇尔·罗德里格兹 Michelle Rodriguez 饰)共度蜜月,布莱恩与米娅退出了赛车界,这支曾环游世界的顶级飞车家族队伍的生活正渐趋平淡。然而,一位神秘女子Cipher(查理兹·塞隆 Charlize T heron 饰)的出现,令整个队伍卷入信任与背叛的危机,面临前所未有的考验。");
movie.setType(MovieType.CARTOON);
运行后,查看数据库,发现movie表中的type字段被赋值2:
mysql> selectname, type from movie;+------------------+------+
| name | type |
+------------------+------+
| 速度与激情8 | 2 |
+------------------+------+
1 row in set (0.00 sec)
如果@Enumerated注解参数配置的是EnumType.STRING,则数据库中会存放枚举对应的字符串值:
mysql> selectname, type from movie;+------------------+---------+
| name | type |
+------------------+---------+
| 速度与激情8 | CARTOON |
+------------------+---------+
1 row in set (0.00 sec)
通过@Enumerated存储在数据库中的值是固定的,是不可定制的,假如枚举类MovieType声明如下:
1 packagestudy.hibernate.model;2
3 public enumMovieType {4 FILM("电影"),5
6 TV("连续剧"),7
8 CARTOON("动漫"),9
10 VARIETY("综艺");11
12 privateString type;13
14 privateMovieType(String type) {15 this.type =type;16 }17
18 @Override19 publicString toString() {20 returntype;21 }22 }
对于如上枚举,希望如果类型为MovieType.CARTOON时,存在数据库中的值为"动漫",如果类型为MovieType.FILM,存在数据库中的值为"电影"。此时@Enumerated的功能是不够的,可以通过指定@Convert注解声明对应的转换类来实现。
@Convert注解用来声明对象在写到数据库的时候怎么转换为数据库可识别的类型,从数据库中读出来的时候怎么反转为对象,可以看作是一个序列化及反序列化的规则。
要使用@Convert注解,首先得定义一个实现了javax.persistence.AttributeConverter接口的类,该接口有两个方法:
javax.persistence.AttributeConverter.convertToDatabaseColumn(X) 用来说明如何把java对象X转换存储在数据库中的数据对象Y;
javax.persistence.AttributeConverter.convertToEntityAttribute(Y) 用来说明如何把数据库中的数据对象Y转换为对应的java对象X;
假如我们的实现类名为MovieTypeConvertor,代码如下:
1 packagestudy.hibernate.model;2
3 importjavax.persistence.AttributeConverter;4
5 public class MovieTypeConvertor implements AttributeConverter{6
7 publicString convertToDatabaseColumn(MovieType attribute) {8 returnString.valueOf(attribute);9 }10
11 publicMovieType convertToEntityAttribute(String dbData) {12 returnMovieType.valueOf(dbData);13 }14
15 }
其次,在数据库Movie.java的type属性上添加@Covert注解
1 @Column(name="TYPE")2 @Convert(converter=MovieTypeConvertor.class)3 private MovieType type;
最后,运行程序,查看数据库中的值,发现数据的值已经被设置为”动漫“
mysql> select name, type frommovie;+------------------+--------+
| name | type |
+------------------+--------+
| 速度与激情8 | 动漫 |
+------------------+--------+
1 row in set (0.00 sec)
@Convert注解并不只能用来匹配注解,它可以用在任何类型的数据上,譬如,可以将一个集合中的内容以空格分隔存在数据库中,读出时以空格分隔重新生成为一个集合等。