2012-08-28 2 views
21

Je suis en train de mettre à jour notre projet Hibernate 3.0 vers Hibernate 4.1.6. (Et nous utilisons actuellement le ressort 3.1)Mise à niveau vers Hibernate 4.1 et l'infâme HibernateTemplate

J'ai lu dans de nombreux articles et dans la documentation de HibernateTemplate, que depuis la version 4.0, HibernateTemplate n'est pas supporté et que je devrais remplacer son utilisation par l'appel sessionFactory.getCurrentSession() pour obtenir une session.

Depuis le début de ce projet avec une version antérieure de Hibernate, où l'utilisation de HibernateTemplate a été encouragée, nous avons présentement 124 utilisations de HibernateTemplate dans notre projet. J'ai peur que remplacer toutes ces occurrences par sessionFactory.getCurrentSession() pourrait insérer des bogues de régression dans notre projet. En outre, il existe certains endroits où HibernateTemplate a été utilisé dans un contexte non transactionnel, où il n'y a pas de session «en cours». Que dois-je faire dans ces cas? Ouvrir une nouvelle session et gérer (fermer) moi-même? Ce n'était pas le cas lorsque j'ai utilisé HibernateTemplate.

Avez-vous une bonne stratégie pour résoudre ces problèmes?

Merci.

lecture pertinente:

  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

Ne pas contribuer à répondre encore bonne lire http://blog.springsource.com/2007/06/26/so-should-you-still-use-springs-hibernatetemplate-andor-jpatemplate/ – xyz

+1

pourrait également être pertinent: https://community.jboss.org/wiki/SessionsAndTransactions – yair

Répondre

11

Ok, Donc, c'est ce que j'ai réellement fait, je ne sais pas si c'est la meilleure solution pour ce problème, mais dans nos circonstances, et puisque je cherchais la solution la plus localisée, il me semblait .

J'ai étendu le springframework.orm.hibernate3.HibernateTemplate et créé un nouveau MyHibernateTemplate. Le rôle principal du nouveau modèle est de remplacer la méthode doExecute que la plupart des hibernate3.HibernateTemplate mènent éventuellement, et de fournir également certaines des fonctionnalités fournies par l'ancien SessionFactoryUtils (comme isSessionTransactional et applyTransactionTimeout).

Le nouveau doExecute réplique la logique de l'ancien, mais au lieu de SessionFactoryUtils.getNewSession pour obtenir une session, il essaie d'abord de rechercher une session ouverte 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()))); 

Vous avez juste besoin de fermer cette session manuellement:

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"); 
     } 
    } 

J'essaie de garder cette réponse courte, mais si vous avez des questions, je peux étendre davantage sur ce problème.

+1

Ceci est un problème difficile en raison de la quantité de fonctionnalités dans HibernateTemplate et ses amis. Avant de trouver ce post, j'avais déjà descendu à peu près la même route que vous décrivez, mais j'ai cloné HibernateTemplate au lieu de l'étendre. Je ne suis pas sûr que c'était la meilleure stratégie. Il me reste beaucoup de fonctionnalités à prendre en compte, donc je suis préoccupé par la stabilité du code qui en résulte. Je sais que c'est de l'histoire ancienne pour vous maintenant, mais pouvez-vous partager plus sur votre stratégie, et comment cela s'est déroulé pour vous? – nclark

2

Découvrez this section dans la documentation. Il est dit que SessionFactory.getCurrentSession() est connectable et qu'une implémentation ThreadLocalSessionContext maintient la 'session en cours' dans la transaction ThreadLocal au lieu d'une transaction JTA. ThreadLocalSessionContext ferme également la session à la fin de la transaction d'hibernation créée à partir de cette session, donc vous n'avez pas à vous soucier de fermer le Session vous-même. En ce qui concerne l'introduction de bogues de régression, la mise à niveau d'une bibliothèque aura toujours des risques, surtout quand c'est quelque chose d'aussi important pour votre application qu'Hibernate. Le seul conseil que je peux donner est de s'assurer que votre suite de tests a une couverture décente avant la mise à niveau. Après tout, c'est le travail de votre suite de tests - pour attraper les bogues de régression.

Questions connexes