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
以及其中区分枚举类型或类别的额外字段。这可以通过具有EnumA
和EnumB
值的内部枚举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映射器来说,它足够具体,因此可以持久化和检索。要指示未设置的值(对于
A
或B
,您可能需要在两个枚举(A
和B
)中添加UNSET
。鉴于这种方法,您还可以查看@PrePersist
(请参阅第 3.5.3 节,第 101 页)以解析字段aEnum
或bEnum
(甚至同时)中的潜在null
值,然后再保存到关联的数据库。