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

ジェネリックは抽象クラス レベルで表示され、具象クラスの場合はクラスごとに 1 つの値しかないため、JPA は提案を完全に処理できます。実際、JPA は、選択した @InheritanceStrategy に従って、サブクラスを 1 つ以上のテーブルに格納し、そのために別のメカニズムを使用します。

ORM が 2 つのクラスを DB に保存する方法について推論して、ケースが問題にならない理由を自分で理解できます。

  • MyStringClass と MyIntegerClass を同じテーブルに格納し、Discriminator 列を追加して、ORM が DB からロードするときに、どのコンストラクターを呼び出す必要があるかを認識できるようにします。
  • すべてのサブクラスを more テーブルに格納できます。

一方、不可能なことは、ジェネリックを定義することです

@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 に保持されませんが、保持され、サブクラス内で一意になります。
  • 私が投稿した 2 番目のケースでは、MyGenericClass の可能な具体的なインスタンスごとに T の値が異なる可能性があり、型消去のためにこの情報は保持されません。

*注意: JPA が 2 番目のケースを処理できないという事実は、まったく合理的であり、そのケースに該当する場合は、設計について自問自答する必要があります。ジェネリックは、他のクラスをタイプ セーフな方法で処理できる柔軟なクラスを設計するための優れたツールですが、タイプ セーフはプログラミング言語の概念であり、永続性とは何の関係もありません。


おまけ: 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 に答える