JPA 完全能够处理您提出的建议,因为泛型出现在抽象类级别,而对于您的具体类,每个类只有一个值。事实上,JPA 将根据您选择的@InheritanceStrategy 将您的子类存储在一个或多个表中,并为此使用不同的机制。
您可以自己弄清楚为什么您的案例不是问题,推理 ORM 如何将这两个类保存在数据库中:
- 您可以将 MyStringClass 和 MyIntegerClass 存储在同一个表中,添加一个 Discriminator 列,以便 ORM 在从 DB 加载时知道应该调用哪个构造函数。
- 您可以将每个子类存储在更多表中。
另一方面,不可能定义一个泛型
@Entity
@Table(name = "MyGenericClass")
public class MyGenericClass<T> {
private T t;
public MyGenericClass(T t) {
this.t=t;
}
}
这样做的原因是,在编译时, T 由于类型擦除而被“擦除”。它在编译时用于验证签名和类型的正确性,但随后它在 JVM 中变成了 java.lang.Object。如果你遵循到现在,你应该能够理解以下内容:
- 在您的情况下, AbstractMyClass 的每个具体子类都有一个类型 T ,该类型是为该类的所有实例定义的。虽然 T 信息不保留在 AbstractMyClass 中,但它在子类中保留且唯一。
- 在我发布的第二种情况下,MyGenericClass 的每个可能的具体实例都可能具有不同的 T 值,并且由于类型擦除,此信息不会保留。
*注意:第二种情况无法由 JPA 处理是绝对合理的,如果您遇到这种情况,您应该问自己有关您的设计的问题。泛型是设计灵活类的好工具,可以以类型安全的方式处理其他类,但类型安全是一种与持久性无关的编程语言概念。
额外:您可以使用 javap 来查看真正的擦除内容。从 MyGenericClass 中取出注释并编译它。
G:\>javac MyGenericClass.java
G:\>javap -p MyGenericClass
Compiled from "MyGenericClass.java"
public class MyGenericClass extends java.lang.Object{
private java.lang.Object t;
public MyGenericClass(java.lang.Object);
}