@Enumerated 注解

JPA 的 @Enumerated 注解非常好用,用来直接映射 enum 枚举类型的字段。@Enumerated 注解可以与 @Basic 注解一起使用,或者当元素集合值是基本类型时,可以与 @ElementCollection 注解一起使用。如果未指定枚举类型或未使用 @Enumerated 注解,则假定 EnumType 值为 ORDINAL。

@Enumerated 注解源码如下:

@Target({METHOD, FIELD}) 
@Retention(RUNTIME)
public @interface Enumerated {
    // 指定映射枚举的类型,默认为 ORDINAL
    EnumType value() default ORDINAL;
}

EnumType

EnumType 枚举定义了枚举类型的映射。此枚举类型的常量指定如何持久化枚举类型的持久属性或字段。可选值如下:

  • ORDINAL:将枚举类型属性或字段持久化为整数;

  • STRING:将枚举类型属性或字段持久化为字符串;

源码:

public enum EnumType {
    // 映射枚举字段的下标
    ORDINAL,
    // 映射枚举字段的name
    STRING
}

实例

(1)创建 users4 表,该表添加了性别枚举字段。SQL 脚本如下:

CREATE TABLE `users4` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',
  `name` varchar(255) DEFAULT NULL COMMENT '姓名',
  `sex` int(10) unsigned DEFAULT NULL COMMENT '年龄',
  PRIMARY KEY (`id`)
) DEFAULT CHARSET=utf8;

(2)定义用户性别枚举类型,代码如下:

public enum SexEnum {
    MALE("男"), FEMALE("女");
    private String value;
    private SexEnum(String value) {
        this.value = value;
    }
}

(3)定义实体,使用 @Enumerated 注解修饰 sex 属性/字段是一个 SexEnum 枚举类型,同时使用枚举的下标作为映射值。代码如下:

import lombok.Data;
import javax.persistence.*;

@Data
@Entity
@Table(name = "users4")
public class User13 {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id;

    @Column
    private String name;

    @Column
    @Enumerated(EnumType.ORDINAL)
    private SexEnum sex;

}

(4)客户端将向 users4 表插入两条数据,性别分别为 SexEnum.MALE 和 SexEnum.FEMALE。然后使用 select 语句将刚刚插入的数据查询出来。代码如下:

import com.alibaba.fastjson.JSONObject;
import com.huangx.openjpa.annotation.entity.SexEnum;
import com.huangx.openjpa.annotation.entity.User13;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;
import java.util.List;

public class OpenJpaDemo13 {
    /** 持久化单元名称 */
    private static final String NAME = "openJPA";

    public static void main(String[] args) {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory(NAME);
        EntityManager em = emf.createEntityManager();
        em.getTransaction().begin();

        // INSERT
        User13 user = new User13();
        user.setName("李四-" + System.currentTimeMillis());
        user.setSex(SexEnum.MALE);
        em.persist(user);

        user = new User13();
        user.setName("李四2-" + System.currentTimeMillis());
        user.setSex(SexEnum.FEMALE);
        em.persist(user);
        System.out.println("insert finished.");

        // SELECT
        String qlString = "select t from User13 t";
        Query query = em.createQuery(qlString);
        List<User13> userList = (List<User13>) query.getResultList();
        for (User13 item : userList) {
            System.out.println(JSONObject.toJSONString(item));
        }

        em.getTransaction().commit();
        em.close();
        emf.close();
        System.out.println("finished.");
    }

}

运行上面客户端代码,执行完成后数据库添加了两条数据,如下图:

其中,id=151 的用户 sex 为 0(SexEnum.MALE 枚举的下标);id=152 的用户 sex 为 1(SexEnum.FEMALE 的下标)。控制台输出如下:

{"id":151,"name":"李四-1622697304567","sex":"MALE"}
{"id":152,"name":"李四2-1622697304660","sex":"FEMALE"}

如果我们将实体的 sex 属性上的 @Enumerated 改为 EnumType.STRING 方式,代码如下:

import lombok.Data;
import javax.persistence.*;

@Data
@Entity
@Table(name = "users4")
public class User13 {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id;

    @Column
    private String name;

    @Column
    @Enumerated(EnumType.STRING)
    private SexEnum sex;

}

记住,这里需要将数据表 sex 字段改为 varchar 类型。SQL 脚本如下:

CREATE TABLE `users4` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',
  `name` varchar(255) DEFAULT NULL COMMENT '姓名',
  `sex` varchar(20) DEFAULT NULL COMMENT '年龄',
  PRIMARY KEY (`id`)
) DEFAULT CHARSET=utf8;

再次运行客户端代码,将数据库中添加如下两条数据:

上面添加的两条用户信息的 sex 字段使用的是枚举 name(注意:是 MALE/FEMALE 不是具体的 “男/女”)。在实际工作中,我们经常会用 EnumType.STRING,如果使用 EnumType.ORDINAL,当我们在枚举类中添加新的枚举值,或枚举值顺序变了,数据库中保存的顺序值就不能与以前的值对应了。控制台输出如下:

{"id":301,"name":"李四-1622697989769","sex":"MALE"}
{"id":302,"name":"李四2-1622697989836","sex":"FEMALE"}
说说我的看法
全部评论(
没有评论
关于
本网站属于个人的非赢利性网站,转载的文章遵循原作者的版权声明,如果原文没有版权声明,请来信告知:hxstrive@outlook.com
公众号