如何使用 JPA 将共享接口的枚举映射到实体的列?


public interface Base { /* anything */ }
public enum A implements Base { /* anything */ }
public enum B implements Base { /* anything */ }
@Entity
public class Clazz 
{
@Column(nullable = false)
private Base base;
...
}

我收到此错误:

Fields "base" are not a default persistent type,
and do not have any annotations indicating their persistence strategy. They will be treated as non-persistent. If you i
ntended for these fields to be persistent, be sure to annotate them appropriately or declare them in orm.xml. Otherwise 
annotate them with @Transient.

我无法从该接口创建抽象类,因为枚举不允许继承。

有谁知道一些解决方法或我有什么选择?

简答

当您尝试将接口类型映射Base并且持久性提供程序(此处:OpenJPA)没有应用于将此相应字段映射到的特定类型的具体信息时,这在您上面发布的场景中永远不会起作用。

长答案

在官方 JPA 2.2 规范的第2.2节持久字段和属性(第 26 页)中,我们发现:

实体的持久字段或属性可以是以下类型:

  • Java 基元类型,

  • java.lang.String,

  • 其他 Java 可序列化类型(包括基元类型的包装器,

    java.math.BigInteger, java.math.BigDecimal, java.util.Date, java.util.Calendar[5], java.sql.Date, java.sql.Time, java.sql.Timestamp, byte[], Byte[], char[], Character[], java.time.LocalDate, java.time.Local- Time, java.time.LocalDateTime, java.time.OffsetTime, java.time.OffsetDa- teTime 和实现可序列化接口的用户定义类型);

  • 枚举;

  • 实体类型;

  • 实体类型的集合;

  • 可嵌入类(参见第 2.5 节);

  • 基本类型和可嵌入类型的集合(请参阅第 2.6 节)。

(数据)仅定义为interface的类型,例如Base,不包括(或排除)在上面的列表中。因此,JPA规范将任何 OR 映射器(也称为持久性提供程序)限制为定义良好具体可序列化的类型,或上述类型的集合。

请注意,类型Base的属性base显然不是枚举本身。

想法

  • (1) 考虑一个常见的枚举类型,例如CommonEnum它携带A和组合的所有枚举值B以及其中区分枚举类型或类别的额外字段。这可以通过具有EnumAEnumB值的内部枚举Category来实现,该枚举将不同类型的类型分开以供以后区分。使用特定的构造函数CommonEnum(value, category)初始化CommonEnum的每个实例。根据需要添加吸气剂/二传手。

  • (2) 鉴于您遵循了 (1) 的思想,您可以通过@Enumerated进行注释(请参阅 JPA 规范的第 11.1.18 节):

    @Entity
    public class Clazz 
    {
    @Enumerated(STRING)
    private CommonEnum commonEnum;
    
  • (3) 如果 (1) + (2) 对您不利,请考虑

    @Entity
    public class Clazz 
    {
    @Enumerated(STRING)
    private A aEnum;
    @Enumerated(STRING)
    private B bEnum;
    

    作为解决方案的想法。可能并不优雅,但是对于OR映射器来说,它足够具体,因此可以持久化和检索。要指示未设置的值(对于AB,您可能需要在两个枚举(AB)中添加UNSET。鉴于这种方法,您还可以查看@PrePersist(请参阅第 3.5.3 节,第 101 页)以解析字段aEnumbEnum(甚至同时)中的潜在null值,然后再保存到关联的数据库。

最新更新