2012-08-28 8 views
21

Uaktualniam nasz projekt z Hibernate 3.0 do Hibernate 4.1.6. (A obecnie za pomocą sprężyny 3.1)Aktualizacja do wersji Hibernuj 4.1 i "niesławny" HibernateTemplate

Czytałem w wielu artykułach oraz w dokumentacji HibernateTemplate, że od wersji 4.0 HibernateTemplate nie jest obsługiwany i że należy wymienić to zwyczaj z wywołaniem sessionFactory.getCurrentSession() uzyskać sesji.

Od czasu uruchomienia tego projektu ze starszą wersją Hibernate, gdzie zachęcono do korzystania z HibernateTemplate, mamy obecnie 124 zastosowania HibernateTemplate w całym naszym projekcie. Obawiam się, że zastąpienie wszystkich tych zdarzeń numerem sessionFactory.getCurrentSession() może spowodować wstawienie błędów regresji do naszego projektu. Ponadto istnieją pewne miejsca, w których HibernateTemplate zostało użyte w kontekście nietransakcyjnym, gdzie nie ma "bieżącej" sesji. Co powinienem zrobić w tych przypadkach? Otwórz nową sesję i sam ją zamknij (zamknij)? Tak się nie stało, gdy użyłem HibernateTemplate.

Czy masz dobrą strategię rozwiązania tych problemów?

Dzięki.

Stosowna czytanie:

  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

Nie przyczynianie się do odpowiedzi nadal dobrze przeczytać http://blog.springsource.com/2007/06/26/so-should-you-still-use-springs-hibernatetemplate-andor-jpatemplate/ – xyz

+1

może być również istotne: https://community.jboss.org/wiki/SessionsAndTransactions – yair

Odpowiedz

11

OK, więc tak właśnie zrobiłem, nie wiem, czy to jest najlepsze rozwiązanie tego problemu, ale w naszych okolicznościach, a ponieważ szukałem najbardziej zlokalizowanego rozwiązania, wydawało mi się najlepiej .

Rozszerzyłem springframework.orm.hibernate3.HibernateTemplate i utworzyłem nowy MyHibernateTemplate. Główną rolą nowego szablonu jest zastąpienie metody doExecute, do której w końcu doprowadziła większość elementu hibernate3.HibernateTemplate, a także dostarczenie niektórych funkcji dostarczanych przez stare obiekty SessionFactoryUtils (takie jak isSessionTransactional i applyTransactionTimeout).

Nowa doExecute replikuje logikę starej, ale zamiast SessionFactoryUtils.getNewSession, aby uzyskać sesję, najpierw spróbuj wyszukać otwartą sesję 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()))); 

Trzeba tylko ręcznie zamknąć tę sesję:

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

Próbuję utrzymać tę odpowiedź krótka, ale czy są jakieś pytania mogę rozwinąć dalej o tym problemie.

+1

Jest to trudny problem ze względu na ilość funkcji w HibernateTemplate i znajomych. Przed znalezieniem tego posta, przeszedłem już w przybliżeniu tą samą drogą, którą opisujesz, ale sklonowałeś HibernateTemplate zamiast go rozszerzać. Nie jestem pewien, czy to była najlepsza strategia. Pozostaje mi wiele funkcji do rozliczenia, więc martwię się o stabilność wynikowego kodu. Wiem, że to już dla ciebie historia starożytna, ale czy możesz podzielić się z nami swoją strategią i dowiedzieć się, jak to dla ciebie rozwinęło? – nclark

2

Wyjazd this section w docs. Mówi, że SessionFactory.getCurrentSession() jest wtykowe i istnieje implementacja ThreadLocalSessionContext, która przechowuje "bieżącą sesję" w transakcji ThreadLocal, a nie JTA. ThreadLocalSessionContext także zamknie sesję na końcu transakcji hibernacji utworzonej z tej sesji, więc nie musisz się martwić o zamknięcie samego siebie Session.

Jeśli chodzi o wprowadzanie błędów regresji, uaktualnienie biblioteki zawsze będzie stanowiło ryzyko, zwłaszcza gdy jest to coś tak istotnego dla aplikacji jak hibernacja. Jedyną radą, jaką mogę dać, jest zapewnienie, że twój pakiet testowy ma przyzwoity zasięg przed aktualizacją. W końcu to jest zadanie twojego zestawu testów - aby złapać błędy regresji.

Powiązane problemy