2012-08-28 9 views
21

Estoy actualizando nuestro proyecto de Hibernate 3.0 a Hibernate 4.1.6. (Y actualmente estamos usando la primavera 3.1)Actualización a Hibernate 4.1 y la "infame" HibernateTemplate

He leído en muchos artículos y en la documentación de HibernateTemplate, que desde la versión 4.0 HibernateTemplate no es compatible y que debería reemplazar su uso con la llamada sessionFactory.getCurrentSession() para obtener una sesión.

Dado que este proyecto se inició con la versión anterior de Hibernate, donde se fomentó el uso de HibernateTemplate, actualmente tenemos 124 usos de HibernateTemplate en todo nuestro proyecto. Me temo que reemplazar todas estas ocurrencias con sessionFactory.getCurrentSession() podría insertar errores de regresión en nuestro proyecto. Además, hay algunos lugares donde se usó HibernateTemplate en un contexto no transaccional, donde no hay una sesión 'actual'. ¿Qué debería hacer en esos casos? ¿Abrir una nueva sesión y manejarla (cerrarla) yo mismo? Ese no fue el caso cuando usé HibernateTemplate.

¿Tiene alguna buena estrategia para abordar estos problemas?

Gracias.

lectura relevantes:

  1. Hibernate Vs. Spring - HibernateTemplate history
  2. Hibernate Core Migration Guide
  3. MIGRATING TO SPRING 3.1 AND HIBERNATE 4.1
  4. org.springframework.orm.hibernate3.HibernateTemplate
+2

No contribuye a la respuesta aún buena lectura http://blog.springsource.com/2007/06/26/so-should-yill-use-springs-hibernatetemplate-andor-jpatemplate/ – xyz

+1

también podría ser relevante: https://community.jboss.org/wiki/SessionsAndTransactions – yair

Respuesta

11

Bien, así que esto es lo que realmente hice, no sé si esta es la mejor solución para este problema, pero en nuestras circunstancias, y como estaba buscando la solución más localizada, me pareció mejor .

He extendido la plantilla springframework.orm.hibernate3.Hibernate y he creado una nueva MyHibernateTemplate. La función principal de la nueva plantilla es anular el método doExecute que la mayoría de hibernate3.HibernateTemplate finalmente genera, y también proporciona parte de la funcionalidad proporcionada por la antigua SessionFactoryUtils (como isSessionTransactional y applyTransactionTimeout).

El nuevo doExecute replica la lógica del antiguo, pero en lugar de SessionFactoryUtils.getNewSession para obtener una sesión, primero intenta buscar una sesión abierta getSessionFactory().getCurrentSession():

boolean newSessionOpened = false; 
Session session; 

if (enforceNewSession){ 
    session = SessionFactoryUtils.openSession(getSessionFactory()); 
    newSessionOpened = true; 
} else { 
    try { 
     // look for an open session 
     session = getSessionFactory().getCurrentSession(); 
    } 
    catch (HibernateException ex) { 
     try { 
      // if there isn't an open session, open one yourself 
      session = getSessionFactory().openSession(); 
      newSessionOpened = true; 
     } catch (HibernateException e) { 
      throw new DataAccessResourceFailureException("Could not open Hibernate Session", ex); 
     } 
    } 
} 

// is the open session, is a session in a current transaction? 
boolean existingTransaction = (!enforceNewSession && 
     (!isAllowCreate() || isSessionTransactional(session, getSessionFactory()))); 

sólo tiene que cerrar la sesión manualmente:

finally { 
    // if session was used in an existing transaction restore old settings 
    if (existingTransaction) { 
     //logger.debug("Not closing pre-bound Hibernate Session after HibernateTemplate"); 
     disableFilters(session); 
     if (previousFlushMode != null) { 
      session.setFlushMode(previousFlushMode); 
     } 
    } 
    // if not and a new session was opened close it 
    else { 
     // Never use deferred close for an explicitly new Session. 
     if (newSessionOpened) { 
      SessionFactoryUtils.closeSession(session); 
      //_log.info("Closing opened Hibernate session"); 
     } 
    } 

Estoy intentando mantener esta respuesta corta, pero si hay cualquier pregunta que pueda dio más detalles sobre este problema.

+1

Este es un problema difícil debido a la cantidad de funcionalidad en HibernateTemplate y sus amigos. Antes de encontrar esta publicación, ya había bajado aproximadamente en el mismo camino que usted describe, pero cloné HibernateTemplate en lugar de extenderlo. No estoy seguro de que sea la mejor estrategia. Me quedan MUCHAS funciones para tener en cuenta, por lo que me preocupa la estabilidad del código resultante. Sé que esta es una historia antigua para ti, pero ¿puedes compartir más sobre tu estrategia y cómo te fue? – nclark

2

Salida this section en la documentación. Dice que SessionFactory.getCurrentSession() es conectable y hay una implementación ThreadLocalSessionContext que mantiene la 'sesión actual' en el ThreadLocal en lugar de una transacción JTA. ThreadLocalSessionContext también cerrará la sesión al final de la transacción de hibernación creada a partir de esa sesión, por lo que no tendrá que preocuparse por cerrar el Session usted mismo.

Con respecto a la introducción de errores de regresión, la actualización de una biblioteca siempre tendrá sus riesgos, especialmente cuando es algo tan esencial para su aplicación como hibernar. El único consejo que puedo dar es garantizar que su suite de pruebas cuente con una cobertura decente antes de la actualización. Después de todo, ese es el trabajo de su suite de pruebas: detectar errores de regresión.

Cuestiones relacionadas