Výnimka režimu dlhodobého spánku: V režime dlhodobého spánku 3 nie je viazaná žiadna relácia dlhodobého spánku na vlákno
Práve som oznámil nové Naučte sa jar kurz zameraný na základy jari 5 a Spring Boot 2:
>> SKONTROLUJTE KURZ1. Úvod
V tomto krátkom návode objasníme, kedy bude vyvolaná výnimka „Žiadna relácia dlhodobého spánku viazaná na vlákno“ a ako ju vyriešiť.
Tu sa zameriame na dva rôzne scenáre:
- pomocou LocalSessionFactoryBean
- pomocou AnnotationSessionFactoryBean
2. Príčina
S verziou 3 predstavil Hibernate koncept kontextovej relácie a getCurrentSession () metóda bola pridaná do SessionFactory trieda. Viac informácií o kontextovej relácii nájdete tu.
Jar má vlastnú implementáciu org.hibernate.context.CurrentSessionContext rozhranie - org.springframework.orm.hibernate3.SpringSessionContext (v prípade jarného zimného spánku 3). Táto implementácia vyžaduje, aby bola relácia viazaná na transakciu.
Prirodzene, triedy, ktoré volajú getCurrentSession () metóda by mala byť anotovaná pomocou @ Transakčné buď na úrovni triedy alebo na úrovni metódy. Ak nie, org.hibernate.HibernateException: Žiadna relácia dlhodobého spánku viazaná na vlákno bude vyhodený.
Poďme sa rýchlo pozrieť na príklad.
3. LocalFactorySessionBean
Je to prvý scenár, na ktorý by sme sa pozreli v tomto článku.
Definujeme konfiguračnú triedu Java Spring pomocou LocalSessionFactoryBean:
@Configuration @EnableTransactionManagement @PropertySource ({"classpath: persistence-h2.properties"}) @ComponentScan ({"com.baeldung.persistence.dao", "com.baeldung.persistence.service"}) verejná trieda PersistenceConfigHibernate3 {// ... @Bean public LocalSessionFactoryBean sessionFactory () {LocalSessionFactoryBean sessionFactory = nový LocalSessionFactoryBean (); Konfigurácia zdrojov = nový ClassPathResource ("exceptionDemo.cfg.xml"); sessionFactory.setDataSource (dataSource ()); sessionFactory.setConfigLocation (config); sessionFactory.setHibernateProperties (hibernateProperties ()); návrat sessionFactory; } // ...}
Upozorňujeme, že používame konfiguračný súbor režimu dlhodobého spánku (exceptionDemo.cfg.xml) tu, aby ste zmapovali triedu modelu. To je preto, že the org.springframework.orm.hibernate3.LocalSessionFactoryBean neposkytuje nehnuteľnosť packagesToScan, pre mapovanie modelových tried.
Tu je naša jednoduchá služba:
@Service @Transactional verejná trieda EventService {@Autowired private IEventDao dao; public void create (entita udalosti) {dao.create (entita); }}
@Entity @Table (name = "EVENTS") verejná trieda Udalosť implementuje Serializable {@Id @GeneratedValue private Long id; popis súkromného reťazca; // ...}
Ako vidíme v útržku kódu nižšie, getCurrentSession () metóda SessionFactory trieda sa používa na získanie relácie dlhodobého spánku:
verejná abstraktná trieda AbstractHibernateDao implementuje IOperations {private Class clazz; @Autowired private SessionFactory sessionFactory; // ... @Override public void create (T entity) {Preconditions.checkNotNull (entity); getCurrentSession (). persist (entity); } chránená relácia getCurrentSession () {návrat sessionFactory.getCurrentSession (); }}
Nasledujúci test úspešne absolvuje a demonštruje, ako bude pri hodine vyvolaná výnimka EventService obsahujúci metódu služby nie je anotovaný s @ Transakčné anotácia:
@RunWith (SpringJUnit4ClassRunner.class) @ContextConfiguration (classes = {PersistenceConfigHibernate3.class}, loader = AnnotationConfigContextLoader.class) verejná trieda HibernateExceptionScen1MainIntegrationTest {@Autowired služba EventService; @ Pravidlo verejné ExpectedException expectEx = ExpectedException.none (); @Test public void whenNoTransBoundToSession_thenException () {expectEx.expectCause (IsInstanceOf.instanceOf (HibernateException.class)); expectEx.expectMessage ("Žiadna relácia dlhodobého spánku viazaná na vlákno," + "a konfigurácia neumožňuje vytvorenie" + "tu mimo transakcie"); service.create (nová udalosť ("z LocalSessionFactoryBean")); }}
Tento test ukazuje, ako sa metóda služby úspešne vykonáva, keď EventService trieda je anotovaná s @ Transakčné anotácia:
@RunWith (SpringJUnit4ClassRunner.class) @ContextConfiguration (classes = {PersistenceConfigHibernate3.class}, loader = AnnotationConfigContextLoader.class) verejná trieda HibernateExceptionScen1MainIntegrationTest {@Autowired služba EventService; @ Pravidlo verejné ExpectedException expectEx = ExpectedException.none (); @Test public void whenEntityIsCreated_thenNoExceptions () {service.create (new Event ("from LocalSessionFactoryBean")); Zoznam udalostí = service.findAll (); }}
4. AnnotationSessionFactoryBean
Táto výnimka sa môže vyskytnúť aj vtedy, keď použijeme org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean vytvoriť SessionFactory v našej jarnej aplikácii.
Pozrime sa na ukážkový kód, ktorý to demonštruje. V tomto rozsahu definujeme konfiguračnú triedu Java Spring pomocou AnnotationSessionFactoryBean:
@Configuration @EnableTransactionManagement @PropertySource ({"classpath: persistence-h2.properties"}) @ComponentScan ({"com.baeldung.persistence.dao", "com.baeldung.persistence.service"}) verejná trieda PersistenceConfig {// ... @Bean public AnnotationSessionFactoryBean sessionFactory () {AnnotationSessionFactoryBean sessionFactory = nový AnnotationSessionFactoryBean (); sessionFactory.setDataSource (dataSource ()); sessionFactory.setPackagesToScan (nový reťazec [] {"com.baeldung.persistence.model"}); sessionFactory.setHibernateProperties (hibernateProperties ()); návrat sessionFactory; } // ...}
S rovnakou sadou tried DAO, Service a Model z predchádzajúcej časti sa stretávame s výnimkou, ktorá je popísaná vyššie:
@RunWith (SpringJUnit4ClassRunner.class) @ContextConfiguration (classes = {PersistenceConfig.class}, loader = AnnotationConfigContextLoader.class) verejná trieda HibernateExceptionScen2MainIntegrationTest {@Autowired služba EventService; @ Pravidlo verejné ExpectedException expectEx = ExpectedException.none (); @Test public void whenNoTransBoundToSession_thenException () {expectEx.expectCause (IsInstanceOf.instanceOf (HibernateException.class)); expectEx.expectMessage ("Žiadna relácia dlhodobého spánku viazaná na vlákno," + "a konfigurácia neumožňuje vytvorenie" + "tu mimo transakcie"); service.create (nová udalosť ("z AnnotationSessionFactoryBean")); }}
Ak anotujeme triedu služby pomocou a @ Transakčné anotácia, metóda služby funguje podľa očakávania a test uvedený nižšie vyhovuje:
@RunWith (SpringJUnit4ClassRunner.class) @ContextConfiguration (classes = {PersistenceConfig.class}, loader = AnnotationConfigContextLoader.class) verejná trieda HibernateExceptionScen2MainIntegrationTest {@Autowired služba EventService; @ Pravidlo verejné ExpectedException expectEx = ExpectedException.none (); @Test public void whenEntityIsCreated_thenNoExceptions () {service.create (new Event ("from AnnotationSessionFactoryBean")); Zoznam udalostí = service.findAll (); }}
5. Riešenie
Je jasné, že getCurrentSession () metóda SessionFactory získané z jari je potrebné zavolať z rámci otvorenej transakcie. Preto riešením je zabezpečiť, aby naše metódy / triedy DAO / Service boli správne anotované pomocou @ Transakčné anotácia.
Je potrebné poznamenať, že v režime dlhodobého spánku 4 a novších verziách je správa o výnimke, ktorá je vyvolaná z rovnakého dôvodu, inak formulovaná. Namiesto „Žiadna relácia dlhodobého spánku viazaná na vlákno ”, dostali by sme „Pre aktuálne vlákno sa nepodarilo získať reláciu synchronizovanú transakciami. “
Je potrebné urobiť ešte jeden dôležitý bod. Spolu s org.hibernate.context.CurrentSessionContext rozhranie, Hibernate predstavil vlastnosť hibernate.current_session_context_class ktorú je možné nastaviť na triedu, ktorá implementuje aktuálny kontext relácie.
Ako už bolo uvedené, jar prichádza s vlastnou implementáciou tohto rozhrania: SpringSessionContext. Predvolene nastavuje hibernate.current_session_context_class majetok rovnajúci sa tejto triede.
V dôsledku toho, ak túto vlastnosť explicitne nastavíme na niečo iné, naruší to Springovu schopnosť spravovať reláciu a transakcie dlhodobého spánku. To má za následok tiež výnimku, ale líši sa to od posudzovanej výnimky.
Ak to zhrnieme, je dôležité mať na pamäti, že by sme nemali stanovovať hibernate.current_session_context_class výslovne, keď na správu relácie hibernácie používame Spring.
6. Záver
V tomto článku sme sa pozreli na to, prečo práve keď výnimka org.hibernate.HibernateException: Žiadna relácia dlhodobého spánku viazaná na vlákno je hodený do režimu dlhodobého spánku 3 spolu s ukážkovým kódom a tým, ako to môžeme ľahko vyriešiť.
Kód tohto článku nájdete na Githube.
Perzistencia dno