2

バックグラウンド

EclipseLink (バージョン 2.3.2.v20111125-r10461、JPA 2.0 仕様の実装プロバイダー) を使用しています。

Person@MappedSuperclassと呼ばれるこれを考えてみましょう:

@MappedSuperclass
@EntityListeners({Listener.class})
public abstract class Person implements Serializable
{
    @Id @GeneratedValue
    private Long id;
}

彼は抽象的で、彼にはリスナー ( Listener ) が付いています。リスナーの実装は次のとおりです。

public class Listener
{
    @PrePersist
    public void sayHi(Person person) {
        System.out.println("Hi!");
    }
}

次に、Personを拡張するEmployeeクラスがあります。

@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class Employee extends Person
{
    private int salary;
}

Employeeはまだ抽象的であり、インスタンス化することを意図していません。ただし、 Employee は関係の一部である可能性があると考えられているため、注釈が付けられて@Entityいます。階層は、PartTimeEmployeeと呼ばれる非抽象エンティティに続きます。

@Entity
public class PartTimeEmployee extends Employee
{
    private int hoursWorked;
}

PartTimeEmployeeはインスタンス化されることを意図しています。それを試して、何が起こるか見てみましょう! 細かい点を除いて、すべて正常に動作しているようです。@MappedSuperclass Personに登録されているエンティティ リスナーは呼び出されません。@EntityListenersアノテーションをPersonからEmployeeに移動しても、リスナーは呼び出されません。

1 つの修正

@EntityListeners注釈をPartTimeEmployeeまで移動すると、彼が呼び出されます。うーん。

別の修正

Personにリスナーを登録したままにすることができ、 Employeeのアノテーションを完全に省略した場合、リスナーは意図したとおりに呼び出されます。しかしもちろん、私は望んでいない単一のテーブル戦略を手に入れました。同様に、ストラテジーの値を から に変更すると、リスナーが呼び出されます。もちろん唯一の問題は、データベース スキーマが思い通りにならないことです。@InheritanceInheritanceType.TABLE_PER_CLASSInheritanceType.SINGLE_TABLE

したがって、ここでの問題の核心は、従業員@Inheritanceクラスの注釈 (より具体的には、クラスごとに 1 つのテーブルへの戦略の変更) であり、階層内のエンティティ リスナーに関するすべてを EclipseLink に忘れさせます。

それは私が期待していたものではありません。私が理解できないのは何ですか?

4

1 に答える 1

1

EclipseLink のバグを見つけたのではないかと思いますが、それらは継承の注釈に共通しています。

EclipseLink の最新バージョンにアップグレードすることをお勧めします。お使いのバージョンは 1 年以上前のものです。それがうまくいかない場合は、派生クラスにリスナーで注釈を付ける必要があります。

特に冒険したい場合は、起動時にリスナーをクラスに追加する SessionCustomizer を実装できます。

于 2013-03-31T05:07:58.423 に答える