复杂数据类型的映射之枚举

枚举

枚举类型规定了取值的数量和内容,这对于需要限定取值的属性非常有帮助。比如性别有三种,男、女、未知,是否打印有两种,是,否。

[java]  view plain  copy
  1. package com.gxz.entities;  
  2.   
  3. public enum Color {  
  4.     RED,  
  5.     GREEN,  
  6.     BLUE  
  7. }  

数据库表

[java]  view plain  copy
  1. CREATE TABLE MyClothes (  
  2.     MyClothesId BIGINT UNSIGNED  PRIMARY KEY AUTO_INCREMENT,  
  3.     Brand VARCHAR(255) NOT NULL,  
  4.     Colour ENUM('RED','GREEN','BLUE'),  
  5.     INDEX MyClothesBrand(Brand)  
  6. ) ENGINE = InnoDB;  
DBMS使用MySQL,字段Colour是枚举类型,只能取值'RED','GREEN','BLUE',若是插入其他值,报出异常。
[sql]  view plain  copy
  1. Operation failed: There was an error while applying the SQL script to the database.  
  2. Executing:  
  3. INSERT INTO `entitymappings`.`myclothes` (`MyClothesId`, `Brand`, `Colour`) VALUES ('1''佐丹奴''BLANK');  
  4.   
  5. ERROR 1265: 1265: Data truncated for column 'Colour' at row 1  
  6. SQL Statement:  
  7. INSERT INTO `entitymappings`.`myclothes` (`MyClothesId`, `Brand`, `Colour`) VALUES ('1''佐丹奴''BLANK')  

实体类

[java]  view plain  copy
  1. package com.gxz.entities;  
  2.   
  3. import javax.persistence.Column;  
  4. import javax.persistence.Entity;  
  5. import javax.persistence.GeneratedValue;  
  6. import javax.persistence.GenerationType;  
  7. import javax.persistence.Id;  
  8. import javax.persistence.Table;  
  9.   
  10. @Entity  
  11. @Table(name="myclothes")  
  12. public class Clothes {  
  13.     private long id;  
  14.     private Colour  colour;  
  15.     private String brand;  
  16.       
  17.     @Id  
  18.     @GeneratedValue(strategy = GenerationType.IDENTITY)  
  19.     @Column(name = "MyClothesId")  
  20.     public long getId() {  
  21.         return id;  
  22.     }  
  23.     public void setId(long id) {  
  24.         this.id = id;  
  25.     }  
  26.     public Colour getColour() {  
  27.         return colour;  
  28.     }  
  29.     public void setColour(Colour colour) {  
  30.         this.colour = colour;  
  31.     }  
  32.     public String getBrand() {  
  33.         return brand;  
  34.     }  
  35.     public void setBrand(String brand) {  
  36.         this.brand = brand;  
  37.     }  
  38.       
  39.       
  40. }  

默认持久化

[java]  view plain  copy
  1. Clothes clothes = new Clothes();  
  2. clothes.setBrand("佐丹奴");  
  3. clothes.setColour(Colour.RED);  
  4.   
  5. manager.persist(clothes);  
此时,报出异常。
[java]  view plain  copy
  1. javax.persistence.PersistenceException: org.hibernate.exception.GenericJDBCException: could not execute statement  
  2. Caused by: org.hibernate.exception.GenericJDBCException: could not execute statement  
  3. Caused by: java.sql.SQLException: Data truncated for column 'Colour' at row 1  
默认情况,JPA实现者使用整数顺序值持久化枚举类型。枚举类型Colour定义取值的顺序是RED、GREEN、BLUE,因此,当这三个取值持久化到数据库表时,取值分别是0、1、2。然而,MySQL数据库表字段Colour是个枚举ENUM类型,只允许存放数值RED、GREEN、BLUE。所以持久化时,就会报出异常。为了印证以上的阐述,修改数据库表,让字段Colour的类型修改为varchar(1),此时,该字段可以存放数值1、2、3。
[java]  view plain  copy
  1. CREATE TABLE MyClothes (  
  2.     MyClothesId BIGINT UNSIGNED  PRIMARY KEY AUTO_INCREMENT,  
  3.     Brand VARCHAR(255) NOT NULL,  
  4.     Colour VARCHAR(1) NOT NULL,  
  5.     INDEX MyClothesBrand(Brand)  
  6. ) ENGINE = InnoDB;  
执行持久化。
[java]  view plain  copy
  1. Clothes clothes = new Clothes();  
  2. clothes.setBrand("佐丹奴");  
  3. clothes.setColour(Colour.RED);  
  4.   
  5. manager.persist(clothes);  
  6.   
  7. Clothes clothes2 = new Clothes();  
  8. clothes2.setBrand("真维斯");  
  9. clothes2.setColour(Colour.GREEN);  
  10.   
  11. manager.persist(clothes2);  
  12.   
  13. Clothes clothes3 = new Clothes();  
  14. clothes3.setBrand("以纯");  
  15. clothes3.setColour(Colour.BLUE);  
  16.   
  17. manager.persist(clothes3);  
查看数据库表myclothes,如下所述。

调整枚举类型Colour取值的定义顺序,刚开始时RED、GREEN、BLUE,现在调整为BLUE、GREEN、RED。
[java]  view plain  copy
  1. package com.gxz.entities;  
  2.   
  3. public enum Colour {  
  4.     BLUE,  
  5.     GREEN,  
  6.     RED  
  7. }  
清空数据库表myclothes,执行持久化,查看数据,如下所述。

如果按照JPA实现者的默认行为执行持久化枚举类型,会有以下问题。
1.我们希望存入数据库的数值是枚举类型的原始数据,比如RED、GREEN、BLUE,而不是0、1、2。
2.如果数据库字段定义是枚举类型,比如Colour ENUM('RED','GREEN','BLUE'),持久化会有异常。
3.如果枚举定义后,修改了取值的顺序,比如刚开始时RED、GREEN、BLUE,后来修改为BLUE、GREEN、RED,持久化到数据库的整数顺序值也会相应的改变,这使得整数顺序值的意义非常混乱。刚开始存放在数据库的整数值,修改枚举的取值顺序后,这些历史数据成了错误的数据。

@Enumerated持久化

注解javax.persistence.Enumerated有唯一的一个属性javax.persistence.EnumType,该属性有两个值,分别是STRING、ORDINAL,意义分别是使用字符类型持久化枚举,使用默认行为持久化枚举。若选择STRING,JPA提供者将使用枚举的原始类型,即常量,持久化枚举,这正是我们希望看到的。

首先,我们把数据库表MyClothes的字段Colour修改回枚举型,接着,使用注解@Enumerated定义实体类。

[java]  view plain  copy
  1. package com.gxz.entities;  
  2.   
  3. import javax.persistence.Column;  
  4. import javax.persistence.Entity;  
  5. import javax.persistence.EnumType;  
  6. import javax.persistence.Enumerated;  
  7. import javax.persistence.GeneratedValue;  
  8. import javax.persistence.GenerationType;  
  9. import javax.persistence.Id;  
  10. import javax.persistence.Table;  
  11.   
  12. @Entity  
  13. @Table(name="myclothes")  
  14. public class Clothes {  
  15.     private long id;  
  16.     private Colour  colour;  
  17.     private String brand;  
  18.       
  19.     @Id  
  20.     @GeneratedValue(strategy = GenerationType.IDENTITY)  
  21.     @Column(name = "MyClothesId")  
  22.     public long getId() {  
  23.         return id;  
  24.     }  
  25.     public void setId(long id) {  
  26.         this.id = id;  
  27.     }  
  28.     @Enumerated(EnumType.STRING)  
  29.     public Colour getColour() {  
  30.         return colour;  
  31.     }  
  32.     public void setColour(Colour colour) {  
  33.         this.colour = colour;  
  34.     }  
  35.     public String getBrand() {  
  36.         return brand;  
  37.     }  
  38.     public void setBrand(String brand) {  
  39.         this.brand = brand;  
  40.     }  
  41.       
  42.       
  43. }  
执行持久化,查询数据库表MyClothes,结果如下所述。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值