12

我想知道带有泛型的抽象类将如何处理 JPA?我的意思是该领域需要什么样的注释?

考虑这些:

@MappedSuperclass
public abstract class AbstractMyClass<T> {
  // What about Strings and Integers? Do I need some kind of @LOB?
  private T field;

  public T getField() {
    return field;
  }

  public void setField(T field) {
    this.field = field;
  }
}

然后这些

@Entity
@Table(name = "String")
public class MyStringClass extends AbstractMyClass<String> {
}

@Entity
@Table(name = "Integer")
public class MyIntegerClass extends AbstractMyClass<Integer> {
}
4

2 回答 2

9

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);
}
于 2012-07-10T11:42:39.583 回答
-2

我们可以。如果T工具Serializable

@Entity
public class IgsSubject extends BasicObject implements Serializable{

    private static final long serialVersionUID = -5387429446192609471L;

@MappedSuperclass
public class IgsBasicLog<T> extends BasicObject {

    @ManyToOne
    @JoinColumn(name = "ITEM_ID")
    private T item;

@Entity
public class IgsLogA extends IgsBasicLog<IgsSubject> implements Serializable {
    private static final long serialVersionUID = -8207430344929724212L;
}
于 2015-12-14T15:07:20.287 回答