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を実行します時閉鎖された原因と解決案