当对应的table有设定值时,在域模型(ORM)中使用Enum?

Use Enum in domain model (ORM) when the corresponding table has set values?

我有一个名为 job_class 的 table,它具有设置值:

这是 table 定义:

create table job_class (
   job_class_code int NOT NULL PRIMARY KEY,
   job_class_name varchar(50) NOT NULL, 
   ext_code varchar(10) NOT NULL
)

它总是有 3 行:

insert into job_class values (1, 'HOURLY', 'H')
insert into job_class values (2, 'SALARY', 'S')
insert into job_class values (3, 'EXECUTIVE', 'E')

job_class table 在 employee table 中被引用为 FK:

create table employee (
   employee_id bigint NOT NULL PRIMARY KEY,
   first_name varchar(50) NOT NULL,
   middle_name varchar(50) NULL,
   last_name varchar(50) NOT NULL,
   job_class_code int NOT NULL FOREIGN KEY REFERENCES job_class (job_class_code)
)

现在要在域模型 (ORM) 中映射这个 table,通常我这样定义一个 class:

public class JobClass implements java.io.Serializable {
   private Integer id;
   private String name;
   private String extCode;

   public Integer getId() { return id; }
   public void setId(Integer id) { this.id = id; }

   public String getName() { return name; }
   public void setName(String name) { this.name = name; }

   public String getExtCode() { return extCode; }
   public void setId(String extCode) { this.extCode = extCode; }
}

但是如果我将其定义为 Enum 会怎样:

public enum JobClass {
   HOURLY(1,"HOURLY","H"),
   SALARY(2,"SALARY","S"),
   EXECUTIVE(3,"EXECUTIVE","E");

   private Integer id;
   private String name;
   private String extCode;

   private JobClass(Integer id, String name, String extCode) {
      this.id = id;
      this.name = name;
      this.extCode = extCode;
   }

   public Integer getId() { return id; }
   public String getName() { return name; }
   public String getExtCode() { return extCode; }
}

在 ORM 中使用 Enum 有意义吗?在此之前,我从未在 ORM 中直接使用过 ENUM。在这种情况下这是一个好习惯吗?如果使用 Enum,Serializable 的含义是什么?

要使用枚举,您必须 100% 确定您的 table 不会有新记录或现有记录被更改,否则您会收到错误消息。

使用 ORM,您将能够通过 @Enumerated 注释映射到枚举,有多种方法可以做到:EnumType.ORDINAL 或 EnumType.STRING.

I'll let you check the documentation for the difference.


在您的情况下,由于您使用自动递增的 ID 作为 FK 键,因此使用 @Enumerated(EnumType.STRING) 并不好,因为它会强制您将枚举值命名为 1、2 和 3。

我不太喜欢使用 @Enumerated(EnumType.ORDINAL),因为它将您的枚举顺序与数据库 table 顺序联系在一起。但在你的情况下它会起作用。

如果您想走得更远,可以使用转换器 @Convert(converter = JobClassConverter.class)

您将保持枚举不变,员工的 jobClass 属性将如下所示:

  @Column(name = "job_class_code")
  @Convert(converter = JobClassConverter.class)
  private JobClass jobClass;

然后您将创建 JobClassConverter

public class JobClassConverter implements AttributeConverter<JobClass, Integer> {

    @Override
    public Integer convertToDatabaseColumn(final JobClass pAttribute) {
        if (pAttribute == null) {
            return null;
        } else {
            switch (pAttribute) {
                case HOURLY:
                    return 1;
                case SALARY:
                    return 2;
                case EXECUTIVE:
                    return 3;
            }
        }
    }

    @Override
    public JobClass convertToEntityAttribute(final Integer pDbData) {
        if (pDbData == null) {
            return null;
        } else {
            switch (pDbData) {
                case 1:
                    return JobClass.HOURLY;
                case 2:
                    return JobClass.SALARY;
                case 3:
                    return JobClass.EXECUTIVE;
            }
        }
    }
}