13

次の階層について考えてみます。ここで、エンティティWidgetAWidgetBは抽象Widgetスーパークラスを拡張します。

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public abstract class Widget implements Serializable  {

    @Column(name="serialNumber", length=64, nullable=false, unique=true)
    private String serialNumber;
    ...

@Entity
public class WidgetA extends Widget implements Serializable  {
...

@Entity
public class WidgetB extends Widget implements Serializable  {
...

でウィジェットを検索する必要がありますserialNumberが、実行時に検索しているウィジェットの具体的なタイプがわかりません。でウィジェットを検索する正しい方法は何ですか?がの場合serialNumber、のインスタンスが返されます。 serialNumberWidgetAWidgetA

findyBySerialNumber()DAOでaを使用しようとするとWidget、抽象クラスをインスタンス化できないというエラーが表示されます。これは理にかなっていますが、永続性プロバイダーは具体的な子エンティティテーブルを調べる方法を知っていると思いました。正しいインスタンスを返します。これをやらせることはできますか?

「SpringDataJPA」を使用しているので、WidgetDAOは非常に単純です。

public interface WidgetDAO extends JpaRepository<Widget, Long> {
    public Widget findBySerialNumber(String serialNumber);
}
4

3 に答える 3

11

ウィジェット階層に明示的に識別子を指定しなかったようです。Spring Dataはバイトコードを操作してクエリを生成するため、明示的に定義してみることができると思います。そのため、SpringDataではこれらの値を明示的に定義する必要があると思います。

さらに、サブクラスでは、各サブクラスの識別子の値を示す必要があります。

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn(name="WIDGET_TYPE")
public abstract class Widget implements Serializable  {

    @Column(name="serialNumber", length=64, nullable=false, unique=true)
    private String serialNumber;
    ...

-

@Entity
@DiscriminatorValue("A")
public class WidgetA extends Widget implements Serializable  {
...

-

@Entity
@DiscriminatorValue("B")
public class WidgetB extends Widget implements Serializable  {
...
于 2013-02-05T20:08:05.937 に答える
4

あなたのオブジェクトと注釈は私にはうまく見えます。それらを取得し、ウィジェットをデータベースに保存して、問題なくフェッチすることができました。

問題はあなたのデータにあると思います。HibernateはWidget、サブクラステーブルのいずれにも対応する行がない行をテーブルで見つけている可能性があるため、スーパークラスのインスタンスを作成しようとして失敗します。

を使用すると、識別子InheritanceType.JOINEDを指定することも、それを自動的に実行することもできます(そのIDの行がサブクラステーブルに存在するかどうかを確認することで信じられます)。ただし、いずれの場合も、データをチェックして、一致するサブクラス行のないスーパークラステーブルにエントリがないことを確認する必要があります。

@Discriminator原則として、クラス階層に明示的に指定する@ben75の推奨事項をサポートします。後でコードを変更しても予期しない方法で値が変更されないように、識別子の値を制御することをお勧めします。

于 2013-02-05T21:26:13.893 に答える
2

Hibernateはそのクエリを問題なくサポートし、正しいサブクラスのインスタンスを喜んで返します。ウィジェットのインスタンスを作成しようとしているのがSpringData実装で何であるかを知らなくても、パーサーを使用するのではなく、クエリを宣言して直接実行することができるはずです。

public interface WidgetDAO extends JpaRepository<Widget, Long> {

    @Query("select w from Widget w where w.serialNumer = ?1")
    public Widget findBySerialNumber(String serialNumber);
}
于 2013-01-15T19:33:03.593 に答える