2011-04-21 26 views
8

Utilizando Hibernate 3.3.0 y ehcache 1.2.3 con caché de segundo nivel y caché de consultas activado, me di cuenta de que el siguiente código devolvía el mismo número de secuencia a varias llamadas, lo que ocasionó una falla en la inserción.¿Las consultas SQL nativas se almacenan en caché de forma predeterminada cuando la caché de consultas de Hibernate está activada?

 HibernateCallback callback = new HibernateCallback() 
     { 
      public Object doInHibernate(Session session) throws HibernateException, SQLException { 
       StringBuilder strQuery = new StringBuilder(); 
       strQuery.append("SELECT "); 
       strQuery.append(sequenceName); 
       strQuery.append(".nextval as nextSequence FROM dual d"); 

       Query query = session.createSQLQuery(strQuery.toString()).addScalar("nextSequence", Hibernate.STRING); 


       return query.uniqueResult(); 
      } 
     }; 
     return this.hibernateTemplate.execute(callback).toString(); 

El código funciona correctamente si apago el caché de consultas o agrego la siguiente línea antes de ejecutar la consulta.

query.setCacheable(false); 

Esto es confuso, ya que Hibernate documentos establecen claramente

mayoría de las consultas no se benefician de almacenamiento en caché, por lo que mediante consultas predeterminadas no son en caché. Para habilitar el almacenamiento en caché, llame al Query.setCacheable (true). Esta llamada permite que la consulta busque resultados de caché existentes o agregue sus resultados a la caché cuando se ejecuta.

En este caso, ¿es este comportamiento anormal y aún puedo asumir que las consultas no están en la memoria caché de forma predeterminada?

Respuesta

4

Query Cache es un mecanismo realmente simple que almacena los resultados para ciertas claves. En caso de consulta nativa, esa clave será su consulta en sí y de todos los parámetros.

Así, por ejemplo, la clave podría ser:

*----------------------------------------------------------------------------------------* 
|         Query Cache           | 
|----------------------------------------------------------------------------------------| 
| ["select * from table as t where t.id=? and p.column=?", [ 1 , "value"] ] -> [ 2 ] ] | 
*----------------------------------------------------------------------------------------* 

Desde esa perspectiva cada consulta puede almacenar en caché - en ciertos escenarios. Por supuesto, la consulta debe ser tratada por las clases de Hibernate, no directamente a través de la conexión JDBC.

Y, por cierto, ¡es fácil averiguar si su consulta usará el caché de consultas o no! Todo está en un archivo de registro bajo org.hibernate.cache.

Y hay un gran inconveniente en todas estas: si ejecuta su consulta nativa, desalojará todas las entidades y registros de la memoria caché de segundo nivel. ¡Al menos lo hizo hasta la última versión que estaba usando! Por lo tanto, puede utilizar consultas nativas de forma correcta, pero como Hibernate no puede decidir qué hacer, borrará la memoria caché para evitar cambios en los datos realizados por esta consulta no reflejada en los objetos de caché.

¡Así que hay un montón de problemas con la caché de consultas y debería considerar si realmente desea usar esa característica! Take a look at this article o this one. Estoy tratando de evitar el uso de cachés de consultas en mi trabajo, solo uso SLC para entidades ...

+0

Información realmente útil sobre el caché de consultas aunque no puedo recordar por qué fue necesario en primer lugar. Sin embargo, el comportamiento de Hibernate como se describió anteriormente sigue siendo extraño. –

Cuestiones relacionadas