JPA实体中的枚举类型字段

时间:2018-02-19 13:51:56

标签: java jpa spring-data-jpa

是否可以将Enums用作自定义JPA实体中的字段(列)类型?这是一个例子:

@Getter @Setter
@Entity
@Table(name = "payments")
public class PaymentEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;

    @Column(name = "status")
    private Integer statusId;

    public PaymentStatuses getStatus() {
        return PaymentStatuses.valueOf(statusId);
    }

    public PaymentEntity setStatus(PaymentStatuses status) {
        statusId = status == null ? null : status.getId();
        return this;
    }
}

public enum PaymentStatuses {
    CREATED(1),
    COMPLETED(2),
    CANCELED(3);


    private Integer id;

    private PaymentStatuses(Integer id) {
        this.id = id;
    }

    public Integer getId() {
         return id;
    }

    public static PaymentStatuses valueOf(Integer id) {
        for (PaymentStatuses value : values())
            if (value.getId().equals(id))
                return value;
        return null;
    }
}

上面的代码运行正常,但使用statusIdgetStatus setStatus的方法看起来很丑陋。

我想在我的实体中使用PaymentStatuses作为字段的类型。像这样:

@Getter @Setter
@Entity
@Table(name = "payments")
public class PaymentEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;

    @Column(name = "status")
    private PaymentStatuses status;
}

请告诉我,是否有可能?

3 个答案:

答案 0 :(得分:4)

使用@Enumerated(EnumType.ORDINAL)无效,因为ORDINAL模式开始为0 因此,枚举的3个第一个值将在带有012值的数据库中表示。
枚举中代表它的枚举中的id字段从1变为3

CREATED(1),
COMPLETED(2),
CANCELED(3);

此外,这种方式会将枚举中定义的元素的顺序与在数据库中表示它们的方式相关联。这可能会在将来添加/删除枚举值,这不是一件好事。

解决问题的更好方法是定义javax.persistence.AttributeConverter并将其与@Convert一起使用 因此,创建一个AttributeConverter实现来指示如何从DB转换为枚举,将枚举转换为DB。
然后在您的实体中声明PaymentStatuses status,并通过指定@Convert实施类,使用AttributeConverter对其进行注释。

@Getter @Setter
@Entity
@Table(name = "payments")
public class PaymentEntity {
  ...
  @Convert(converter = PaymentStatusesConverter.class)
  private PaymentStatuses status;
  ...    
}

public class PaymentStatusesConverter  implements AttributeConverter<PaymentStatuses, Integer> {

    @Override
    public Integer convertToDatabaseColumn(PaymentStatuses status) {
        return status.getId();
    }

    @Override
    public PaymentStatuses convertToEntityAttribute(Integer status) {
         return PaymentStatuses.valueOf(status); 
    }
}

答案 1 :(得分:1)

是的,但是当您保存到数据库时,它将保留枚举值的当前索引(在您的情况下为0表示CREATED,1表示COMPLETED等),如果您更改枚举值,这将给您带来麻烦。为避免这种情况,您可以使用@Enumerated注释,如:

@Getter @Setter
@Entity
@Table(name = "payments")
public class PaymentEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;

    @Column(name = "status")
    @Enumerated(EnumType.ORDINAL) // There is also EnumType.STRING, or you can define a custom EnumType
    private PaymentStatuses status;
}

答案 2 :(得分:0)

如果您希望将数据存储在数据库中,可以使用bool,例如Java枚举名称的名称(@Enumerated(EnumType.STRING)