Spring @Transactional-永続化/マージ後にコレクションを使用する

collections java spring transactions
Spring @Transactional-永続化/マージ後にコレクションを使用する

アプリケーションでSpringとJPAを使用していますが、最近、DomainObjectsのコレクションの使用に少し混乱しました。

例えば:

親と子の2つのテーブルがあるとします。 親は複数の子(@OneToMany)を持つことができ、子は1つの親(@ManyToOne)のみを持つことができます。 Springを使用して、ServiceLayerでトランザクションコンテキストを処理します(Daoではありません
– 作業単位パターン)、context-application.xmlで構成されます
aop:configによって。 子コレクションは、LazyLoadingコレクションとしてマークされます。 これまではすべてうまくいきました。

問題は次のとおりです。

サービスにメソッドが必要です。このメソッドは、新しい親を作成し、同じトランザクションで別のメソッドを呼び出して、新しく作成された親でいくつかの計算を行います。 これらの計算の中で、parent.getChildren()を呼び出す必要があります。 新しい親は作成時に子を持つことができないため、これは明らかに空のセットを返す必要がありますが、何らかの理由で空のセットではなく「null」が返され、NullpointerExceptionが発生します

親を作成するには、次のEntityManagerメソッドを試しました。

  1. entityManager.persist(parent)を使用-うまくいかなかった、コレクションは
    作成後はnull。

  2. entityManager.merge(parent)を使用して、新しいマネージドを返します
    親のインスタンス-同じ結果がありました。

両方ともnullセットになりました。 しかし、これらの呼び出しは同じトランザクション内にあり、トランザクションの外部では、この時点で(afaik)正しいLazyLoadingException(NullPointerの代わりに)を受け取ることになります。 一方、entityManager.findById()で既存の親を使用すると、既存のコレクションが生成されます(つまり、期待どおりに動作することを意味します)。問題を解決するために、動作するものが見つかるまでいくつかのアプローチを試みました。

リフレッシュを呼び出すとコレクションが初期化されるため、マージ/永続化が完了した後のentityManager.refresh(parent)。

しかし、チュートリアルでは、この方法が使用されていることは一度も見ませんでした。 EntityManagerのJavaDocでは、マージは新しいマネージドBeanを返し、persistは参照自体をマネージドと言います。 管理されているとは、トランザクション内でそれらのコレクションを既に使用できることを意味すると推測しました。 作成時にコレクションが初期化されないのはなぜですか? たとえば、Parentのコンストラクタで自分で初期化する必要がありますか?

何か間違ったことをしたのか、それとも新しい親インスタンスを作成した後にrefresh()を呼び出すのが正しい方法なのでしょうか? もしそうなら、次の記事で推奨されているように、私は永続化と更新を分離する必要があるだけです:http://blog.xebia.com/2009/03/23/jpa-implementation-patterns-saving-detached-entities/ [ [JPA実装]および永続化後に新しく作成されたオブジェクトを更新しますか? または、本当にコレクションを使用する必要があるときに、オブジェクトを更新するだけですか?

あなたが私をフォローしてくれて、その点について明確にするための推奨事項や解決策をいただければ幸いです。

ありがとうございました、+ ymene

  1  0


ベストアンサー

コレクションフィールドを初期化しますか?

@OneToMany
private Set foos = new HashSet();

ただではなく

@OneToMany
private Set foos;

後者はもちろんNPEをスローするためです。

4


親クラスでCascadeType.ALLを使用してみてください。

@OneToMany(cascade = CascadeType.ALL)
public List getChildren() {
  return children;
}

次に、OpenSessionInViewFilterを使用します。 これにより、ビューからparent.getChildren()を呼び出すことができ、応答が返されるまで休止状態セッションが開いたままになります。 以下は、web.xmlで設定する方法です。

 OpenSessionInViewFilter
 com.isavera.hibernate.OpenSessionFilter

     singleSession
 false




 OpenSessionInViewFilter
 /*

お役に立てれば

0


タイトルとURLをコピーしました