6

私はここで途方に暮れています.Hibernateの専門知識が他の分野よりも弱いため、おそらくそれは明らかなことです.

レガシー コードには Hibernate@EntityクラスがありFooます。そのプロパティの 1 つを次に示します。

private OldBar bar = new OldBar();

OldBar@Embeddable、単一の列を使用するクラスですfoobar:

@Embeddable
public class OldBar {

  private String fooBar;

  @Column(length = 10, nullable = false)
  private String getFooBar() {
    return fooBar;
  }

  @SuppressWarnings("unused")
  private void setFooBar(String fooBar) {
    this.fooBar = fooBar;
  }
}

元の問題は、 で何かをする必要があったことですOldBar.fooBarが、元の設計には制限があり、このフィールドを非公開にしていたため、サブクラス化できませんでした。そのため、別のクラス全体を作成して、他のクラスNewBarを置き換えてアクセスできるようにする必要がありました。プライベート フィールド。NewBarEmbeddable同じ指定を持っているので@Column、クラスのフィールドを交換するだけでよいと思いましたFoo:

private NewBar bar = new NewBar();

列に既存のデータがあり、foobarこのデータを透過的に使用したかったので、これを行いたかったNewBarOldBarです。

コンストラクターが呼び出されたときに、予想どおり、Foo()デフォルト バージョンの が作成されることをトレース ログで確認しました。NewBar()しかし、コードが を呼び出すFoo.getBar()までに、何らかの理由barnull! nullHibernate が何らかの理由で に設定していると思いますが、Hibernate がfoobar列からデータを読み取って のインスタンスを作成しないのはなぜNewBarですか? OldBarの代わりに戻すと、再び機能するようになるのはなぜNewBarですか? 確かに、データベース自体には、どの@Embeddableクラスが列にマップされているかを示すものは何もありませんよね?

更新:これはますます奇妙になります。コードを一晩放置して、翌日には機能することもあります。または次の日はうまくいきません!ちょうど今うまくいかなかった (つまり、データベースの値の代わりにfoobarプロパティが設定されていた) ので、クラスを作成して .の代わりに配置しました。うまくいきました!そこで、一時的な変更を元に戻すだけに戻ります。以前は機能していなかったのに、まだ機能していました。Hibernate が値をシリアル化し、データベースから取得しないようなキャッシュはありますか? これは非常に奇妙です。nullExactCopyOfOldBarOldBarNewBar

更新:今、私はまったく仕事に就くことができなくなりNewBarました。を作成します。これは、名前が異なることOtherBarを除いて基本的には と同じです。プラグインすると、埋め込まれた文字列を正しく読み取って動作します。NewBarに切り替えるNewBarと、再び取得nullします。何が起こっている?

Fooがロードされていることに注意してくださいnet.databinder.auth.hib.AuthDataApplication.getUser(String username)。これは非常に単純です。

return (DataUser) Databinder.getHibernateSession().createCriteria(getUserClass())
    .add(Restrictions.eq("username", username)).uniqueResult();

Foo(ユーザー)テーブルに正しいデータを含む単一の行があること、そして最も重要なことに、foobarフィールドにデータがあることを何度も確認しました。Fooなぜ Hibernate は私にnull foobarフィールドを返すのですか? NewBarから切り替えるだけで、OtherBar再び機能し始めるのはなぜですか? 一日中動作し、一晩放置すると動作しなくなるのはなぜですか?

4

1 に答える 1

1

これが答えかもしれません。それが本当に問題を解決するかどうかを確認するために数日待つ必要があります。実際には2つの部分があります。

まず、完全に開示するために、私のNewBarクラスは実際にはのサブクラスでしAbstractBarた。結局、別の種類の埋め込み可能なバーが欲しかったので@EmbeddableAbstractBarレベルではなくNewBarレベルに配置し、プライベートfoobarフィールドもAbstractBarレベルに配置しました。面白いことに、これは時々機能しました。そして、私が言ったように、時々私は翌日戻ってきて、Hibernateはfoobarフィールドをロードしませんでした。なぜそれがいつも動かなかったのか、いつも動かなかったのか理解できません。

次に、問題の原因の1つを排除するためにこの階層を取り除こうとしたとき、私は混乱AbstractBarしましたが、からまでを上げるNewBarのを忘れていたため、Hibernateはそれが埋め込み可能なクラスであるとは認識せず、知りませんでした。指定なしで文字列をフィールドにロードする方法。これが、(注釈付きで)機能したが(注釈なしで)機能しなかった理由です。これだけ理解しています。なぜHibernateがフィールドをロードする方法を理解できないと警告しなかったのか、私にはわかりません。@EmbeddableAbstractBarNewBarNewBar@EmbeddableOtherBar@EmbeddableNewBar@Embeddable

@Embeddable要約すると、アノテーションをクラスから除外した場合、Hibernateは埋め込み可能フィールドをロードしません。@Embeddable元の問題については、クラス階層で使用しようとすると不安定であり、すべての埋め込み可能フィールドを埋め込み可能クラスの1つのレベルに保持するのが最善であると推測できます。それが問題だといいのですが。明日も機能するかどうかを確認します。

于 2012-04-22T17:23:19.487 に答える