2010-09-13 24 views
10

He cargado una entidad en mi transacción y he cambiado una propiedad de esa entidad. La transacción aún no está comprometida. Ahora me gustaría obtener el valor original de la propiedad modificada.Solicitud Force Hibernate para acceder a la base de datos

He intentado con una consulta HQL como select p.property from Person p where p.id = 1 con el ID de la entidad cargada en la transacción.

He configurado query.setHint("org.hibernate.cacheMode", CacheMode.IGNORE); antes de ejecutar la consulta. Pero no hay éxito Hibernate devuelve el valor establecido en la transacción actual, no el de la base de datos.

¿Hay alguna forma de evitar esto?

+0

¿No terminas con el problema donde Hibernate se queja de que la misma entidad está en la sesión dos veces? Parece que quizás quieras volver a visitar la implementación. –

Respuesta

11

He cargado una entidad en mi transacción y he cambiado una propiedad de esa entidad. La transacción aún no está comprometida. Ahora me gustaría obtener el valor original de la propiedad modificada.

En resumen: realice un seguimiento del valor anterior usted mismo.

He intentado con una consulta HQL como seleccionar p.propiedad desde Person p donde p.id = 1 con el ID de la entidad cargada en la transacción.

Hibernate carga una versión única de una entidad en la sesión (el primer nivel de caché) para un identificador de base de datos dado. Esto no funcionará

He configurado query.setHint ("org.hibernate.cacheMode", CacheMode.IGNORE); antes de ejecutar la consulta.

Esta pista se utiliza para afectar a la caché consulta (que se basan en el segundo nivel de caché), esto no afectará a su "problema" actual.

¿Hay alguna forma de evitar esto?

De cualquier

  • uso session.refresh() para forzar una recarga de su entidad (y perderás los cambios)
  • tienda el valor anterior como se mencionó inicialmente.
  • invocar un servicio que realiza una consulta en otra transacción.
2

Esto puede ayudar:

Si desea forzar la caché de consultas para refrescar una de sus regiones (desatender ningún resultado en caché que encuentra allí) se puede utilizar org.hibernate.Query .setCacheMode (CacheMode.REFRESH). En conjunto con la región que ha definido para la consulta dada, Hibernate forzará selectivamente los resultados en caché en esa región particular que se va a actualizar. Esto es particularmente útil en los casos en datos subyacentes pueden haber sido actualizados a través de un proceso separado y es una medida más eficiente alternativa a granel desalojo de la región a través de org.hibernate.SessionFactory.evictQueries().

(De http://docs.jboss.org/hibernate/stable/core/reference/en/html/performance.html, sección 20.4.2).

Sin embargo, está destinado a utilizarse cuando otro proceso está actualizando la base de datos, y debe utilizarse con cuidado. Su caso es diferente. Como este método ocurre fuera de cualquier transacción, debe asegurarse de que no entre en conflicto con su diseño. Tal vez pueda refactorizar su flujo de llamadas para evitar ese comportamiento, y recuperar el campo desde otra fuente o antes de que ocurra la modificación en la memoria caché ...

+0

Al revisar mi respuesta, veo que no resuelve completamente su problema. Incluso si deshabilita por completo la memoria caché de segundo nivel, los datos de su entidad pueden venir para la memoria caché de primer nivel (sesión). Para eso, debe actualizar o desalojar el objeto ... pero luego debe volver a ingresar los campos que desea guardar en la confirmación de la transacción. – Sebastian

1

La única forma de hacerlo sería ejecutar la consulta fuera del transacción actual.

7

The StatelessSession funcionó para mí.

StatelessSession statelessSession = sessionFactory.openStatelessSession(); 
try { 
    return statelessSession.get(Ticket.class, ticketKey, LockMode.READ) 
} finally { 
    statelessSession.close() 
} 
Cuestiones relacionadas