Dvaletilstand: Undtagelse: Ingen dvale-session bundet til tråden i dvaletilstand 3

Udholdenhedstop

Jeg har lige annonceret det nye Lær foråret kursus med fokus på det grundlæggende i Spring 5 og Spring Boot 2:

>> KONTROLLER KURSEN

1. Introduktion

I denne korte vejledning Vi klarlægger, hvornår undtagelsen "Ingen dvale-session bundet til tråd" bliver kastet, og hvordan man løser det.

Vi fokuserer her på to forskellige scenarier:

  1. bruger LocalSessionFactoryBean
  2. bruger AnnotationSessionFactoryBean

2. Årsagen

Med version 3 introducerede Hibernate konceptet for den kontekstuelle session og getCurrentSession () metoden blev føjet til SessionFactory klasse. Flere oplysninger om den kontekstuelle session kan findes her.

Foråret har sin egen implementering af org.hibernate.context.CurrentSessionContext grænseflade - org.springframework.orm.hibernate3.SpringSessionContext (i tilfælde af Spring Hibernate 3). Denne implementering kræver, at sessionen er bundet til en transaktion.

Naturligvis klasser, der kalder getCurrentSession () metoden skal kommenteres med @Transaktionel enten på klasseniveau eller metodeniveau. Hvis ikke, org.hibernate.HibernateException: Ingen dvale-session bundet til tråd vil blive kastet.

Lad os se hurtigt på et eksempel.

3. LocalFactorySessionBean

Han er det første scenarie, som vi ville se på i denne artikel.

Vi definerer en Java Spring-konfigurationsklasse med LocalSessionFactoryBean:

@Configuration @EnableTransactionManagement @PropertySource ({"classpath: persistence-h2.properties"}) @ComponentScan ({"com.baeldung.persistence.dao", "com.baeldung.persistence.service"}) offentlig klasse PersistenceConfigHibernate3 {// ... @Bean public LocalSessionFactoryBean sessionFactory () {LocalSessionFactoryBean sessionFactory = ny LocalSessionFactoryBean (); Ressource konfiguration = ny ClassPathResource ("exceptionDemo.cfg.xml"); sessionFactory.setDataSource (dataSource ()); sessionFactory.setConfigLocation (config); sessionFactory.setHibernateProperties (hibernateProperties ()); retur sessionFabrik; } // ...}

Bemærk, at vi bruger en dvale-konfigurationsfil (exceptionDemo.cfg.xml) her for at kortlægge modelklassen. Dette er fordi det org.springframework.orm.hibernate3.LocalSessionFactoryBean leverer ikke ejendommen PackagesToScan, til kortlægning af modelklasser.

Her er vores enkle service:

@Service @Transactional public class EventService {@Autowired private IEventDao dao; offentlig tomrum oprette (Begivenhedsenhed) {dao.create (enhed); }}
@Entity @Table (name = "EVENTS") offentlig klasse Event implementerer Serialiserbar {@Id @GeneratedValue privat Lang id; privat streng beskrivelse; // ...}

Som vi kan se i nedenstående kodestykke, er getCurrentSession () metode til SessionFactory klasse bruges til at opnå dvale-sessionen:

offentlig abstrakt klasse AbstractHibernateDao implementerer IOperations {private Class clazz; @Autowired privat SessionFactory sessionFactory; // ... @ Overstyr offentlig tomrum oprette (T-enhed) {Forudsætninger.checkNotNull (enhed); getCurrentSession (). persist (enhed); } beskyttet Session getCurrentSession () {return sessionFactory.getCurrentSession (); }}

Testen nedenfor består og viser, hvordan undtagelsen vil blive kastet, når klassen EventService der indeholder servicemetoden, er ikke kommenteret med en @Transaktionel kommentar:

@RunWith (SpringJUnit4ClassRunner.class) @ContextConfiguration (classes = {PersistenceConfigHibernate3.class}, loader = AnnotationConfigContextLoader.class) public class HibernateExceptionScen1MainIntegrationTest {@Autowired EventService service; @Regel offentlig ExpectedException expectEx = ExpectedException.none (); @Test offentlig ugyldig nårNoTransBoundToSession_thenException () {forventetEx.expectCause (IsInstanceOf.instanceOf (HibernateException.class)); expectEx.expectMessage ("Ingen dvale-session bundet til tråd," + "og konfiguration tillader ikke oprettelse" + "af en ikke-transaktionel her"); service.create (ny begivenhed ("fra LocalSessionFactoryBean")); }}

Denne test viser, hvordan servicemetoden udføres med succes, når EventService klasse er kommenteret med @Transaktionel kommentar:

@RunWith (SpringJUnit4ClassRunner.class) @ContextConfiguration (classes = {PersistenceConfigHibernate3.class}, loader = AnnotationConfigContextLoader.class) public class HibernateExceptionScen1MainIntegrationTest {@Autowired EventService service; @Regel offentlig ExpectedException expectEx = ExpectedException.none (); @Test offentlig ugyldig nårEntityIsCreated_thenNoExceptions () {service.create (ny begivenhed ("fra LocalSessionFactoryBean")); Liste begivenheder = service.findAll (); }}

4. AnnotationSessionFactoryBean

Denne undtagelse kan også forekomme, når vi bruger org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean at oprette SessionFactory i vores forårsprogram.

Lad os se på en prøvekode, der demonstrerer dette. I dette omfang definerer vi en Java Spring-konfigurationsklasse med AnnotationSessionFactoryBean:

@Configuration @EnableTransactionManagement @PropertySource ({"classpath: persistence-h2.properties"}) @ComponentScan ({"com.baeldung.persistence.dao", "com.baeldung.persistence.service"}) offentlig klasse PersistenceConfig {// ... @Bean public AnnotationSessionFactoryBean sessionFactory () {AnnotationSessionFactoryBean sessionFactory = ny AnnotationSessionFactoryBean (); sessionFactory.setDataSource (dataSource ()); sessionFactory.setPackagesToScan (ny streng [] {"com.baeldung.persistence.model"}); sessionFactory.setHibernateProperties (hibernateProperties ()); retur sessionFabrik; } // ...}

Med det samme sæt DAO-, service- og modelklasser fra det foregående afsnit støder vi på undtagelsen som beskrevet ovenfor:

@RunWith (SpringJUnit4ClassRunner.class) @ContextConfiguration (classes = {PersistenceConfig.class}, loader = AnnotationConfigContextLoader.class) public class HibernateExceptionScen2MainIntegrationTest {@Autowired EventService service; @Regel offentlig ExpectedException expectEx = ExpectedException.none (); @Test offentlig ugyldig nårNoTransBoundToSession_thenException () {forventetEx.expectCause (IsInstanceOf.instanceOf (HibernateException.class)); expectEx.expectMessage ("Ingen dvale-session bundet til tråden," + "og konfiguration tillader ikke oprettelse" + "af en ikke-transaktionel her"); service.create (ny begivenhed ("fra AnnotationSessionFactoryBean")); }}

Hvis vi kommenterer serviceklassen med en @Transaktionel kommentar, servicemetoden fungerer som forventet, og testen vist nedenfor består:

@RunWith (SpringJUnit4ClassRunner.class) @ContextConfiguration (classes = {PersistenceConfig.class}, loader = AnnotationConfigContextLoader.class) public class HibernateExceptionScen2MainIntegrationTest {@Autowired EventService service; @Regel offentlig ExpectedException expectEx = ExpectedException.none (); @Test offentlig ugyldig nårEntityIsCreated_thenNoExceptions () {service.create (ny begivenhed ("fra AnnotationSessionFactoryBean")); Liste begivenheder = service.findAll (); }}

5. Løsningen

Det er klart, at getCurrentSession () metode til SessionFactory hentet fra Spring skal kaldes fra en åben transaktion. Derfor, løsningen er at sikre, at vores DAO / servicemetoder / klasser er kommenteret korrekt med @Transaktionel kommentar.

Det skal bemærkes, at i dvaletilstand 4 og senere versioner er meddelelsen om undtagelsen, der smides af samme grund, forskelligt formuleret. I stedet for “Ingen dvale-session bundet til tråd ”, vi får “Kunne ikke hente transaktions-synkroniseret session for den aktuelle tråd ”.

Der er et andet vigtigt punkt at komme med. Sammen med org.hibernate.context.CurrentSessionContext interface har Hibernate introduceret en ejendom hibernate.current_session_context_class som kan indstilles til den klasse, der implementerer den aktuelle sessionskontekst.

Som tidligere nævnt kommer Spring med sin egen implementering af denne grænseflade: SpringSessionContext. Som standard indstiller den hibernate.current_session_context_class ejendom svarende til denne klasse.

Som en konsekvens, hvis vi eksplicit sætter denne egenskab til noget andet, forstyrrer det Springs evne til at styre dvale-sessionen og transaktionerne. Dette resulterer også i en undtagelse, men er forskellig fra den pågældende undtagelse.

Sammenfattende er det vigtigt at huske, at vi ikke skal indstille hibernate.current_session_context_class eksplicit når vi bruger Spring til at styre dvale-sessionen.

6. Konklusion

I denne artikel så vi på, hvorfor en når undtagelsen org.hibernate.HibernateException: Ingen dvale-session bundet til tråd kastes i dvale 3 sammen med nogle eksempler på kode og hvordan vi nemt kan løse det.

Koden til denne artikel kan findes på Github.

Persistens bund

Jeg har lige annonceret det nye Lær foråret kursus med fokus på det grundlæggende i Spring 5 og Spring Boot 2:

>> KONTROLLER KURSEN