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

Perzistencia hore

Práve som oznámil nové Naučte sa jar kurz zameraný na základy jari 5 a Spring Boot 2:

>> SKONTROLUJTE KURZ

1. Ú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:

  1. pomocou LocalSessionFactoryBean
  2. 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

Práve som oznámil nové Naučte sa jar kurz zameraný na základy jari 5 a Spring Boot 2:

>> SKONTROLUJTE KURZ

$config[zx-auto] not found$config[zx-overlay] not found