2011-03-03 12 views
5

Soy nuevo en hibernación y primavera y experimento con la memoria caché de segundo nivel de hibernación. Pero parece que no funciona. Tengo una clase de prueba siguientes:Configuración de la memoria caché de segundo nivel de hibernación

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(locations = { "classpath:applicationContext.xml" }) 
@TransactionConfiguration 
@Transactional 
public class CacheTest extends AbstractTransactionalJUnit4SpringContextTests 
{ 
    @Test 
     public void testCache1() 
     { 
     System.out.println("Running testCache1"); 
     ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml"); 
     MutableDAO<AppUser> appUserDAO = new MutableDAOImpl<AppUser>(AppUser.class, (SessionFactory) ctx.getBean("OnMediaSessionFactory"), 10); 
     assertNotNull("AppUser DAO is null.", appUserDAO); 

     SessionFactory sessionFactory = (SessionFactory)ctx.getBean("OnMediaSessionFactory"); 
     long numberOfUsers = appUserDAO.countAll(); 

     System.out.println("Number of rows :" + numberOfUsers); 
     final String cacheRegion = AppUser.class.getCanonicalName(); 

     SecondLevelCacheStatistics settingsStatistics = sessionFactory.getStatistics(). 
      getSecondLevelCacheStatistics(cacheRegion); 
     StopWatch stopWatch = new StopWatch(); 
     stopWatch.start(); 
     appUserDAO.findAll(); 
     stopWatch.stop(); 
     System.out.println("Query time : " + stopWatch.getTotalTimeSeconds()); 
     System.out.println(settingsStatistics); 
    } 

    @Test 
    public void testCache2() 
    { 
     System.out.println("Running testCache2"); 
     ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml"); 
     MutableDAO<AppUser> appUserDAO = new MutableDAOImpl<AppUser>(AppUser.class, (SessionFactory) ctx.getBean("OnMediaSessionFactory"), 10); 
     assertNotNull("AppUser DAO is null.", appUserDAO); 

     SessionFactory sessionFactory = (SessionFactory)ctx.getBean("OnMediaSessionFactory"); 
     long numberOfUsers = appUserDAO.countAll(); 

     System.out.println("Number of rows :" + numberOfUsers); 
     final String cacheRegion = AppUser.class.getCanonicalName(); 

     SecondLevelCacheStatistics settingsStatistics = sessionFactory.getStatistics(). 
      getSecondLevelCacheStatistics(cacheRegion); 
     StopWatch stopWatch = new StopWatch(); 
     stopWatch.start(); 
     appUserDAO.findAll(); 
     stopWatch.stop(); 
     System.out.println("Query time : " + stopWatch.getTotalTimeSeconds()); 
     System.out.println(settingsStatistics); 
    } 
} 

y tengo

<prop key="hibernate.show_sql">false</prop> 
<prop key="hibernate.format_sql">true</prop> 
<prop key="hibernate.use_sql_comments">true</prop> 
<prop key="hibernate.cache.use_query_cache">true</prop> 
<prop key="hibernate.cache.use_second_level_cache">true</prop> 
<prop key="hibernate.generate_statistics">true</prop> 
<prop key="hibernate.cache.use_structured_entries">true</prop> 

pero me da salida como esta:

Running testCache1 
Number of rows :81 
Query time : 0.129 
SecondLevelCacheStatistics[hitCount=0,missCount=0,putCount=81,elementCountInMemory=81,elementCountOnDisk=0,sizeInMemory=219634] 
Running testCache2 
Number of rows :81 
Query time : 0.063 
SecondLevelCacheStatistics[hitCount=0,missCount=0,putCount=81,elementCountInMemory=81,elementCountOnDisk=0,sizeInMemory=219634] 

lo que tengo que hacer para conseguir que funcione?

+0

Las clases de entidad en sí tiene que ser hecho de manera explícita cacheables - han hecho esto? – skaffman

+0

sí, tengo @Cache (usage = CacheConcurrencyStrategy.READ_WRITE) – Daniel

Respuesta

3

Su prueba es muy extraña, crea un contexto de aplicación nuevo para cada prueba, por lo tanto, Hibernate SessionFactory no sobrevive entre las pruebas, así como su caché de segundo nivel.

correcta del test se vería así:

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(locations = { "classpath:applicationContext.xml" }) 
public class CacheTest extends AbstractTransactionalJUnit4SpringContextTests 
{ 
    @Autowired 
    private MutableDAO<AppUser> appUserDAO; 

    @Autowired 
    private SessionFactory sessionFactory; 

    private TransactionTemplate tx; 

    @Autowired 
    public void setPtm(PlatformTransactionManagement ptm) { 
     tx = new TransactionTemplate(ptm); 
    } 

    @Test 
    public void doTestCache() { 
     // Using programmatic transaction management since we need 2 transactions 
     // inside the same method 

     // 1st attempt 
     tx.execute(new TransactionCallbackWithoutResult() { 
      public void doInTransactionWithoutResult(TransactionStatus status) { 
       testCache(); 
      } 
     }); 

     // 2nd attempt 
     tx.execute(new TransactionCallbackWithoutResult() { 
      public void doInTransactionWithoutResult(TransactionStatus status) { 
       testCache(); 
      } 
     }); 

    } 

    public void testCache() { 
     long numberOfUsers = appUserDAO.countAll(); 

     System.out.println("Number of rows :" + numberOfUsers); 
     final String cacheRegion = AppUser.class.getCanonicalName(); 

     SecondLevelCacheStatistics settingsStatistics = sessionFactory.getStatistics(). 
      getSecondLevelCacheStatistics(cacheRegion); 
     StopWatch stopWatch = new StopWatch(); 
     stopWatch.start(); 
     appUserDAO.findAll(); 
     stopWatch.stop(); 
     System.out.println("Query time : " + stopWatch.getTotalTimeSeconds()); 
     System.out.println(settingsStatistics); 
    }  
} 
+0

Gracias por su respuesta. Pero ¿qué es @Autowired public void setPtm (PlatformTransactionManagement ptm) { tx = new TransactionTemplate (ptm); } y en Platform PlatformTransactionManagement? – Daniel

+0

@Daniel: es necesario para la gestión de transacciones programáticas, consulte [10.6 Gestión de transacciones programáticas] (http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/transaction.html#transaction -programático). Como desea verificar que los valores almacenados en caché sobrevivan entre transacciones, debe ejecutar varias transacciones dentro de un método de prueba, y la administración de transacciones programáticas es una buena forma de organizarlo. – axtavt

+0

ejecuté su código pero ahora obtengo Número de filas: 81 Tiempo de consulta: 0.142 SecondLevelCacheStatistics [HitCount = 0, misscount = 0, putCount = 0, elementCountInMemory = 0, elementCountOnDisk = 0, sizeInMemory = 0] Número de filas: tiempo 81 de consulta: 0.031 SecondLevelCacheStatistics [HitCount = 0, misscount = 0, putCount = 0, elementCountInMemory = 0, elementCountOnDisk = 0, sizeInMemory = 0] – Daniel

2

En primer lugar, recordar que Hibernate no utiliza cualquier proveedor de caché por defecto. Por lo tanto, necesitará un proveedor de caché "externo" para la memoria caché de 2L de Hibernate. Para mi respuesta, usaré ehcache e Hibernate 3.3. Tenga en cuenta que la configuración se modificó en versiones más recientes de Hibernate, por lo tanto, lea los documentos de la versión exacta que está utilizando.

En la configuración de Hibernate, omitió una parte, que es apuntar Hibernate al proveedor real. La propiedad hibernate.cache.provider_class hace eso para Hibernate 3.3. Establecer su valor a net.sf.ehcache.hibernate.SingletonEhCacheProvider

Ahora, tendrá también un ehcache.xml, así:

<?xml version="1.0" encoding="UTF-8"?> 
<ehcache> 

    <diskStore path="./cache" /> 

    <defaultCache maxElementsInMemory="10000" 
        eternal="true" 
        overflowToDisk="true" 
        diskPersistent="true" 
        diskExpiryThreadIntervalSeconds="120" 
        memoryStoreEvictionPolicy="FIFO" /> 

    <cache name="com.mycompany.jpa.MyEntity" 
      maxElementsInMemory="50" 
      overflowToDisk="true" /> 

    <cache name="org.hibernate.cache.StandardQueryCache" 
      maxElementsInMemory="50" 
      overflowToDisk="true" /> 

    <cache name="org.hibernate.cache.UpdateTimestampsCache" 
      maxElementsInMemory="5000" 
      overflowToDisk="true" /> 

</ehcache> 

Usted no mostró su DAO, así, no estoy seguro de que es correcto o no . Tenga en cuenta que siempre debe ser explícito acerca de la caché, ya que está destinado a ser una solución para lugares específicos, en lugar de una solución genérica para todo. Eso significa que, en su DAO, debe agregar una sugerencia de consulta, indicando que su consulta es almacenable en caché (de su prueba, parece que quiere el caché de consultas, no solo el caché de entidades).

Si aún no puede hacerlo funcionar, consulte el archivo adjunto en la siguiente JIRA. Contiene un proyecto Maven con caché habilitada, así, puede ser capaz de compararlo con el código:

https://issues.jboss.org/browse/JBPAPP-4224

Cuestiones relacionadas