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

    xiaoxiao2021-03-26  4

    枚举

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

    [java]  view plain  copy package com.gxz.entities;      public enum Color {       RED,       GREEN,       BLUE   }  

    数据库表

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

    实体类

    [java]  view plain  copy package com.gxz.entities;      import javax.persistence.Column;   import javax.persistence.Entity;   import javax.persistence.GeneratedValue;   import javax.persistence.GenerationType;   import javax.persistence.Id;   import javax.persistence.Table;      @Entity   @Table(name="myclothes")   public class Clothes {       private long id;       private Colour  colour;       private String brand;              @Id       @GeneratedValue(strategy = GenerationType.IDENTITY)       @Column(name = "MyClothesId")       public long getId() {           return id;       }       public void setId(long id) {           this.id = id;       }       public Colour getColour() {           return colour;       }       public void setColour(Colour colour) {           this.colour = colour;       }       public String getBrand() {           return brand;       }       public void setBrand(String brand) {           this.brand = brand;       }                 }  

    默认持久化

    [java]  view plain  copy Clothes clothes = new Clothes();   clothes.setBrand("佐丹奴");   clothes.setColour(Colour.RED);      manager.persist(clothes);   此时,报出异常。 [java]  view plain  copy javax.persistence.PersistenceException: org.hibernate.exception.GenericJDBCException: could not execute statement   Caused by: org.hibernate.exception.GenericJDBCException: could not execute statement   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 CREATE TABLE MyClothes (       MyClothesId BIGINT UNSIGNED  PRIMARY KEY AUTO_INCREMENT,       Brand VARCHAR(255) NOT NULL,       Colour VARCHAR(1) NOT NULL,       INDEX MyClothesBrand(Brand)   ) ENGINE = InnoDB;   执行持久化。 [java]  view plain  copy Clothes clothes = new Clothes();   clothes.setBrand("佐丹奴");   clothes.setColour(Colour.RED);      manager.persist(clothes);      Clothes clothes2 = new Clothes();   clothes2.setBrand("真维斯");   clothes2.setColour(Colour.GREEN);      manager.persist(clothes2);      Clothes clothes3 = new Clothes();   clothes3.setBrand("以纯");   clothes3.setColour(Colour.BLUE);      manager.persist(clothes3);   查看数据库表myclothes,如下所述。 调整枚举类型Colour取值的定义顺序,刚开始时RED、GREEN、BLUE,现在调整为BLUE、GREEN、RED。 [java]  view plain  copy package com.gxz.entities;      public enum Colour {       BLUE,       GREEN,       RED   }   清空数据库表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 package com.gxz.entities;      import javax.persistence.Column;   import javax.persistence.Entity;   import javax.persistence.EnumType;   import javax.persistence.Enumerated;   import javax.persistence.GeneratedValue;   import javax.persistence.GenerationType;   import javax.persistence.Id;   import javax.persistence.Table;      @Entity   @Table(name="myclothes")   public class Clothes {       private long id;       private Colour  colour;       private String brand;              @Id       @GeneratedValue(strategy = GenerationType.IDENTITY)       @Column(name = "MyClothesId")       public long getId() {           return id;       }       public void setId(long id) {           this.id = id;       }       @Enumerated(EnumType.STRING)       public Colour getColour() {           return colour;       }       public void setColour(Colour colour) {           this.colour = colour;       }       public String getBrand() {           return brand;       }       public void setBrand(String brand) {           this.brand = brand;       }                 }   执行持久化,查询数据库表MyClothes,结果如下所述。

    转载请注明原文地址: https://ju.6miu.com/read-500239.html

    最新回复(0)