2012-01-16 12 views
2

私は、エンティティは、以下のように定義されています:JPAのEntityManagerのキャッシング

find操作はエンティティマネージャで行われたときに、私は、見ることができるものから、
public class Version { 
    @Id 
    private Long id; 
    private String content; 
    @Transient 
    private Model model; 

    //... 
} 

が、それは一度だけ、基礎となるデータベースにSELECTを行い、その後、エンティティはエンティティマネージャにキャッシュされます。しかし、modelプロパティにModelを割り当てると、この変更はキャッシュされたエンティティに反映されないことがわかります。例えば。あるコールでfind操作が実行され、Modelが割り当てられている場合、別のEJBからもう一度findを実行すると、modelプロパティは再びnullになります。この変更はキャッシュされたエンティティに反映されませんか?おそらくそれは@Transientですか?

答えて

7

エンティティマネージャは第1レベルキャッシュを保持し、この第1レベルキャッシュはトランザクションが終了するとすぐに破棄されます。そうでなければ、同じアプリケーション内または別のトランザクション内の他のトランザクションがキャッシュされたエンティティを変更または削除できるため、キャッシュは失効した値を返します。

さらに、同時トランザクションはそれぞれ独自のセッションレベルキャッシュを持ち、したがって同じエンティティの独自のインスタンスを持ちます。

次のトランザクションで同じエンティティfindが発行された場合、新しいSQLクエリが発行され、エンティティの別のインスタンスが返されます。

特定のエンティティのトランザクション間で何かを記憶しなければならない場合は、データベースに永続化する必要があります。それがデータベースのポイントです。

+0

ありがとうございますが、2番目のEJB呼び出し(ログレベルはFINESTに設定されています)で発行される新しいSQLクエリは表示されません。トランザクション管理はデフォルトに設定されています。理由は何でしょうか? – Dario

+0

EJB1はEJB2を呼び出していますか、またはクライアント呼び出しEJB1を持っていて、クライアント呼び出しEJB2はありますか?どのような取引であるか、取引開始時と停止時を理解していますか? –

+0

Webサービスを通じて呼び出されるEJBは1つだけです。 2つの連続したWebサービス呼び出しが同じメソッドに行われます。最初の呼び出しでは、ログに 'SELECT'クエリがあります。 2番目の呼び出しでは、クエリはまったくありません。 – Dario

2

EclipseLinkを使用している場合、過渡状態の共有キャッシュへのマージは2通りの方法で設定できます。

@ CloneCopyPolicyを使用すると、一時コンテキストのオブジェクトが共有キャッシュにクローンされ、一時フィールドが保持されます。

@InstantiationCopyPolicyを使用すると、新しいインスタンスが共有キャッシュ用に作成され、一時的なデータは保存されません。

織りとフィールドアクセスを使用している場合、デフォルトは@CloneCopyPolicy、それ以外の場合は@InstantiationCopyPolicyです。

また、DescriptorEventListenerとpostMerge/postCloneイベントを使用して、共有キャッシュにマージされるものを制御することもできます。

2

@JB Nizetに同​​意する必要があります。 JPAのEntityManagerとHibernateのセッションは、拡張されたPersistence Contextを提供します。 「最初のレベルのキャッシュは、トランザクションが終了するとすぐに破棄されます」ということはまったく当てはまりません。

永続コンテキストはトランザクションの長さのために取引Scoped--永続 コンテキストの生活 'のいずれか、または 永続コンテキストは、複数のトランザクションにわたってExtended--することができます。

https://blogs.oracle.com/carolmcdonald/entry/jpa_caching

ソリューションが正しい、あなたはそれがキャッシュに変更する場合は、オブジェクトへの変更を永続化する必要があります。

関連する問題