5

データの永続化に Hibernate を使用し、Spring を (適切な測定のために) 使用するアプリケーションがあります。最近まで、アプリケーションには 1 つの永続クラス A がありました。

@Entity
public class A {
  @Id
  @Column(unique = true, nullable = false, updatable = false)
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private long id;
  public String name;
}

それ以来、B と呼ばれる A のサブクラスを追加しました。

@Entity
public class B extends A {
  public String description;
}

B を追加した後、A をロードできなくなりました。次の例外がスローされました:

class org.springframework.orm.hibernate3.HibernateObjectRetrievalFailureException :: Object with id: 1 was not of the specified subclass: A (Discriminator: null); nested exception is org.hibernate.WrongClassException: Object with id: 1 was not of the specified subclass: A (Discriminator: null)

Bに以下のアノテーションとプロパティを追加したところ、問題が解決したようです。これは問題を解決する正しい方法ですか?

...
@DiscriminatorFormula("(CASE WHEN dtype IS NULL THEN 'A' ELSE dtype END)")
public class A {
    private String dtype = this.getClass().getSimpleName();
    ...
4

1 に答える 1

2

(...) 最近まで、アプリケーションには 1 つの永続クラス A: がありました。

次のデータベース表現を使用します。

ID  NAME
--  ----
 1   foo
 2   bar

それ以来、B と呼ばれる A のサブクラスを追加しました (...)

Inheritanceまた、アノテーションを指定しなかったため、SINGLE_TABLEマッピング戦略が使用されます。この戦略では、階層内のすべてのクラスが 1 つのテーブルにマップされます。テーブルには、「識別子列」として機能する列があります。つまり、行によって表されるインスタンスが属する特定のサブクラスを識別する値を持つ列です。

その後、テーブルは次のようになりました。

ID  NAME DTYPE
--  ---- -----
 1   foo  NULL
 2   bar  NULL

DTYPE は、識別子に使用される列のデフォルト名です。

B を追加した後、A をロードできなくなりました。次の例外がスローされました (...)

実際、既存の値の識別子列に null 値があるため、プロバイダーはインスタンス化するサブクラスを認識できません。

Bに以下のアノテーションとプロパティを追加したところ、問題が解決したようです。これは問題を解決する正しい方法ですか?

これは 1 つの方法ですが、侵入的 (エンティティは列を認識してはいけませんdtype) であり、Hibernate 固有です。言い換えれば、それはハックです。

私にとって、これを解決する「正しい」方法はDTYPE、既存の A レコードの列を更新して値を設定することです'A'(Hibernate では、値はデフォルトでエンティティ名になります)。

UPDATE A SET DTYPE='A' WHERE DTYPE=NULL

このようにして、Hibernate はそれらを適切にロードできます。

于 2010-08-03T04:12:16.007 に答える