JPA实体中的枚举类型字段

3

是否可以在自定义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;
    }
}

上面的代码运行良好,但是使用statusIdgetStatussetStatus的方法看起来有点丑陋。

我想把PaymentStatuses作为实体中字段的类型。就像这样:

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

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

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

请告诉我,这是可能的吗?


1
您可以使用@Enumerated(EnumType.ORDINAL)。 - Klaimmore
@Klaimmore ORDINAL0 开始。它与用于表示 DB 中枚举的 ID (123) 不兼容。 - davidxxx
3个回答

7
使用@Enumerated(EnumType.ORDINAL)将无法正常工作,因为ORDINAL模式从0开始。
所以枚举的前3个值将用012的值表示在数据库中。
而枚举中的id字段表示在数据库中从13
CREATED(1),
COMPLETED(2),
CANCELED(3);

此外,这种方式会将枚举中定义的元素顺序与它们在数据库中的表示方式相关联。这并不是一个好事情,因为枚举值可能会在未来添加/删除。
解决您的问题的更好方法是定义一个javax.persistence.AttributeConverter,并使用@Convert进行转换。
因此,创建一个AttributeConverter实现,指示如何从DB转换为枚举和枚举到DB。
然后在您的实体中声明一个PaymentStatuses status,并通过指定AttributeConverter实现类对其进行注释@Convert
@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); 
    }
}

谢谢。一切正常。Spring Data JPA查找查询也很好用。 - Bohdan Petrenko
1
@Bohdan Petrenko 感谢您的反馈。不用客气。 - davidxxx
这个在从数据库中获取值时运行良好。但是在插入到数据库时会抛出转换异常。提前致谢。 - Rajesh

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;
}

0

如果你想要将数据存储在数据库中,就可以使用@Enumerated(EnumType.STRING),这样数据会以Java枚举名称(CREATED, COMPLETED, CANCELED)的形式存储。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接