Invalidating JPA EntityManager sessionで説明されているような問題に直面しています:
問題: 古いデータの取得
別のアプリケーションによって同時に変更される SQL データベースで JPQL クエリを実行しています。Tomcat で動作する JSF+Spring+EclipseLink を使用しています。
JPQL クエリを実行するクラスはシングルトン Spring Bean であり、注入された を使用しますEntityManager
。
@Component
public class DataRepository{
@PersistenceContext
private EntityManager entityManager;
public List<MyDTO> getStuff(long id) {
String jpqlQuery ="SELECT new MyDTO([...])";
TypedQuery<MyDTO> query = entityManager.createQuery(jpqlQuery,MyDTO.class);
return query.getResultList();
}
[...]
(コードの言い換え)。
問題は、このコードがデータベースで直接実行された変更を認識しないことです。これらの変更は、Tomcat インスタンスが再起動された場合にのみ表示されます。
私たちが試したこと
EntityManager
リンクされた質問で説明されているように、この動作は に関連付けられた第 1 レベルのキャッシュが原因であると想定しています。2 つの解決策が見つかりました。
- 呼び出す
entityManager.clear()
前に呼び出しますcreateQuery
(これはリンクされた質問で提案されています) EntityManagerFactor
(を使用して)を注入し、クエリごと@PersistenceUnit
に新しいを作成して閉じますEntityManager
どちらのソリューションも、私たちが望むことを行います - 新しいデータを取得します。
質問:
- これら2つの解決策は正しいですか?どちらの方がよいですか?
- 特に、注入された EntityManager を安全に呼び出すことができます
entityManager.clear()
か、それとも (同じクラスまたは別のクラスで) 注入された EntityManager も使用する他のコードに何らかの影響を与えますか? - 別のより良いアプローチはありますか?キャッシュを更新したい、または更新したいことをどうにかして宣言できます
EntityManager
か?
これはかなり一般的な問題だと思います(複数のアプリがデータベースを共有するたびに発生するため)ので、簡単な解決策があるはずだと思いました...