1

JavaeeアプリケーションでJPAを使用しています。クラスAにマップされたテーブルAがあります。エンティティにクエリを実行すると(たとえば、そのIDで)、常に別のオブジェクトが返されます。例:

public A getAById(int id) {
    A obj = (A) em.createNamedQuery("getAById")
            .setParameter("id", id).getSingleResult();
    return obj;
}

public void test(){
    getAById(1)==getAById(1) //is false
}

データベースからクエリを実行するときに常に新しいインスタンスを作成するのではなく、既にクエリが実行されている場合は既存のオブジェクトを返すようにJPAに指示する方法はありますか?

//編集この記事は私を大いに助けました:http: //en.wikibooks.org/wiki/Java_Persistence/Caching#Example_JPA_2.0_Cacheable_annotation

4

3 に答える 3

3

データベースからクエリを実行するときに常に新しいインスタンスを作成するのではなく、既存のオブジェクトがまだクエリされていない場合はそれを返すようにJPAに指示する方法はありますか?

JPAは、選択したクエリに対して新しいエンティティを作成することはありません。次の例を参照してください

Query qry = em.createNamedQuery("SELECT r FROM BusinessUnit r WHERE r.buKey = :buKey");
Object result1 = qry.setParameter("buKey", "32").getSingleResult();
qry = em.createNamedQuery("SELECT r FROM BusinessUnit r WHERE r.buKey = :buKey");
Object result2 = qry.setParameter("buKey", "32").getSingleResult();
System.out.println(result1 == result2);

上記の場合、メソッドはエンティティクラスで上書きされるため、私はresult1 == result2trueになります。hashCode

エンティティクラスがequalsメソッドを上書きする場合は、オブジェクト参照と比較する代わりに、equalsメソッドを使用してテストできます。

public void test(){
    getAById(1).equals(getAById(1)) ;
}
于 2013-02-06T12:18:42.040 に答える
2

JavaEEコンテナはJPAプロバイダーのEntityManagerをプロキシでラップするため、コンテナがトランザクションの外部で新しいEMを取得するために表示される動作が発生する可能性があります。2つのgetAById(1)呼び出しは、カバーの下にある2つの異なるEntityManagerに送信されます。これらを単一のトランザクションでラップし、トランザクションの存続期間中、コンテナーに同じエンティティマネージャーを使用させることで、これを回避できます。

于 2013-02-06T13:14:49.910 に答える
-2

永続コンテキストに既存のエンティティインスタンスがすでに存在する場合は、はい。ただし、entityManager.find(entity.class、id)などのEntityManager操作を使用する必要があります。これを行うと、entitymanagerは、関連付けられたPersistenceContextからエンティティを最初に見つけるように求められます。見つからない場合は、DBからクエリを実行します。エンティティインスタンスが関連付けられたPersistenceContextに初めて読み込まれると、同じエンティティIDに対する残りのクエリはDBクエリをトリガーせず、PersistenceContextにキャッシュされているクエリを常に再利用します。これはJPAの第1レベルのキャッシュです。

JPQLはPersistenceContextをバイパスし、常にDBと直接通信するため、 JPQLの使用は要件に適合しません。これにより、異なるJavaオブジェクト(主キーに関して同じエンティティ)が取得されることになります。

于 2013-02-06T12:17:26.727 に答える