jpaをテストする時に注意する必要がある二級キャッシュ
5236 ワード
最近、統合テストを書いて、エンティティ+セットキャッシュのプログラムをテストします。単独で実行しても大丈夫です。複数のテストケースが一緒に実行されると、第二の出現から第一のテストケースセットにロードされる可能性がある内容になります。
テストケース:
最初のテストケース:
1、sqlをロードすることにより、
User〓〓1
farms
Farm钾1
Farm钮2
2、次の実行に問題はない。
第二のテストケース:
1、sqlをロードすることにより、
User〓〓1
farms
Farm舸3
Farm铄4
Farm葃5
2、続いてjpaを呼び出す:
entityManager.get EnttityManager Factory().getCache().evictAll();キャッシュを空にします。
entityManager.clear()キャッシュをクリアします
3、次は発見されます。
User铉1で得られたfarmsは、まだFarm铅1、Farm葃2で、新しく積載されたのではなく、最初のテストケースを得たのです。
これはなぜですか?
jpaはキャッシュの概念がないので、hibernateに特有なものです。だから、entityManager.get EnttityManager Factory().getCache().evictAll() エンティティキャッシュのみをクリアし、エンティティに対応するセットキャッシュはまだ存在するので、データベースを調べて最新のものを取得しません。
jpa Cacheに関する概念はhttp://en.wikibooks.org/wiki/Java_Persistence/Cachingを参照することができる。
ヒベルナjpa cacheの実現コードは以下の通りです。
public void evictAll() {
sessionFactory.getCache().evictEntityRegions();
// TODO : if we want to allow an optional clearing of all cache data, the additional calls would be:
//sessionFactory.getCache().evictCollectionRegions();
//sessionFactory.getCache().evictQueryRegions();
}
集合キャッシュを削除できるアプリを探してみます。entityManager.get EnttityManager Factory().getCache()にはありません。どうすればいいですかこの場合は、ヒベルナのSession Factoryを取得して、二級キャッシュをクリアするしかありません。
したがって、ツールクラスを書きました。
/**
* Copyright (c) 2005-2012 https://github.com/zhangkaitao
*
* Licensed under the Apache License, Version 2.0 (the "License");
*/
package com.sishuok.es.common.repository.hibernate;
import org.hibernate.Cache;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.ejb.HibernateEntityManagerFactory;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
/**
* jpa api hibernate api
* <p>User: Zhang Kaitao
* <p>Date: 13-5-23 6:24
* <p>Version: 1.0
*/
public class HibernateUtils {
/**
* jpa EntityManager hibernate Session API
* @param em
* @return
*/
public static Session getSession(EntityManager em) {
return (Session) em.getDelegate();
}
/**
* jpa EntityManager hibernate SessionFactory API
* @see #getSessionFactory(javax.persistence.EntityManagerFactory)
* @param em
* @return
*/
public static SessionFactory getSessionFactory(EntityManager em) {
return getSessionFactory(em.getEntityManagerFactory());
}
/**
* jpa EntityManagerFactory hibernate SessionFactory API
* @param emf
* @return
*/
public static SessionFactory getSessionFactory(EntityManagerFactory emf) {
return ((HibernateEntityManagerFactory)emf).getSessionFactory();
}
/**
* jpa EntityManager hibernate Cache API
* @see #getCache(javax.persistence.EntityManagerFactory)
* @param em
* @return
*/
public static Cache getCache(EntityManager em) {
return getCache(em.getEntityManagerFactory());
}
/**
* jpa EntityManagerFactory hibernate Cache API
* @param emf
* @return
*/
public static Cache getCache(EntityManagerFactory emf) {
return getSessionFactory(emf).getCache();
}
/**
*
* @param em
*/
public static void clearLevel1Cache(EntityManager em) {
em.clear();
}
/**
* jpa EntityManager
* @see #clearLevel2Cache(javax.persistence.EntityManagerFactory)
* @param em
*/
public static void clearLevel2Cache(EntityManager em) {
clearLevel2Cache(em.getEntityManagerFactory());
}
/**
* jpa EntityManagerFactory :
* 1、
* 2、
* 3、
* :
* jpa Cache api evict , 。。。
* @see org.hibernate.ejb.EntityManagerFactoryImpl.JPACache#evictAll()
*
* @param emf
*/
public static void clearLevel2Cache(EntityManagerFactory emf) {
Cache cache = HibernateUtils.getCache(emf);
cache.evictEntityRegions();
cache.evictCollectionRegions();
cache.evictDefaultQueryRegion();
cache.evictQueryRegions();
cache.evictNaturalIdRegions();
}
}
この場合は、clearLevel 2 Cacheを呼び出して、2つのキャッシュのすべての内容をクリアすることができます。
関連記事:
jpaとjdbcを混合して試験を統合します時Connectionは第二回sqlを実行します時閉鎖された原因と解決案