JPA 的 @Enumerated 注解非常好用,用来直接映射 enum 枚举类型的字段。@Enumerated 注解可以与 @Basic 注解一起使用,或者当元素集合值是基本类型时,可以与 @ElementCollection 注解一起使用。如果未指定枚举类型或未使用 @Enumerated 注解,则假定 EnumType 值为 ORDINAL。
@Enumerated 注解源码如下:
@Target({METHOD, FIELD})
@Retention(RUNTIME)
public @interface Enumerated {
// 指定映射枚举的类型,默认为 ORDINAL
EnumType value() default ORDINAL;
}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"}