HibernateException: No Hibernate Session bound to thread in Hibernate 3

Utholdenhetstopp

Jeg kunngjorde nettopp det nye Lær våren kurs, med fokus på det grunnleggende i vår 5 og vårstøvel 2:

>> KONTROLLER KURSET

1. Introduksjon

I denne korte opplæringen, Vi vil avklare når “No Hibernate Session Bound to Thread” unntaket blir kastet og hvordan vi kan løse det.

Vi fokuserer her på to forskjellige scenarier:

  1. bruker LocalSessionFactoryBean
  2. bruker KommentarSessionFactoryBean

2. Årsaken

Med versjon 3 introduserte Hibernate konseptet med den kontekstuelle økten og getCurrentSession () metoden ble lagt til SessionFactory klasse. Mer informasjon om kontekstøkten finner du her.

Våren har sin egen implementering av org.hibernate.context.CurrentSessionContext grensesnitt - org.springframework.orm.hibernate3.SpringSessionContext (i tilfelle Spring Hibernate 3). Denne implementeringen krever at økten er bundet til en transaksjon.

Naturligvis klasser som ringer getCurrentSession () metoden skal merkes med @Transaksjonell enten på klassenivå eller metodenivå. Hvis ikke, org.hibernate.HibernateException: Ingen dvalemodus økt bundet til tråd vil bli kastet.

La oss se raskt på et eksempel.

3. LocalFactorySessionBean

Han er det første scenariet vi ser på i denne artikkelen.

Vi vil definere en Java Spring-konfigurasjonsklasse 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 (); Resource config = new ClassPathResource ("exceptionDemo.cfg.xml"); sessionFactory.setDataSource (dataSource ()); sessionFactory.setConfigLocation (config); sessionFactory.setHibernateProperties (hibernateProperties ()); returøktFabrikk; } // ...}

Merk at vi bruker en dvalemodus-konfigurasjonsfil (exceptionDemo.cfg.xml) her for å kartlegge modellklassen. Dette er fordi de org.springframework.orm.hibernate3.LocalSessionFactoryBean gir ikke eiendommen PackagesToScan, for kartlegging av modellklasser.

Her er vår enkle tjeneste:

@Service @ Transaksjonell offentlig klasse EventService {@Autowired privat IEventDao dao; public void create (Event entity) {dao.create (entity); }}
@Entity @Table (name = "EVENTS") offentlig klasse Event implementerer Serialiserbar {@Id @GeneratedValue private Lang id; privat strengbeskrivelse; // ...}

Som vi kan se i kodebiten nedenfor, getCurrentSession () metoden for SessionFactory klasse brukes til å få dvalemodus:

offentlig abstrakt klasse AbstractHibernateDao implementerer IOperations {private Class clazz; @Autowired privat SessionFactory sessionFactory; // ... @ Overstyr offentlig tomrom opprette (T-enhet) {Forutsetninger.checkNotNull (enhet); getCurrentSession (). vedvarer (enhet); } beskyttet Session getCurrentSession () {return sessionFactory.getCurrentSession (); }}

Testen nedenfor består og viser hvordan unntaket blir kastet når klassen EventService som inneholder tjenestemetoden, er ikke kommentert med en @Transaksjonell kommentar:

@RunWith (SpringJUnit4ClassRunner.class) @ContextConfiguration (classes = {PersistenceConfigHibernate3.class}, loader = AnnotationConfigContextLoader.class) public class HibernateExceptionScen1MainIntegrationTest {@Autowired EventService service; @Rule public ExpectedException expectEx = ExpectedException.none (); @Test offentlig ugyldig nårNoTransBoundToSession_thenException () {forventetEx.expectCause (IsInstanceOf.instanceOf (HibernateException.class)); expectEx.expectMessage ("Ingen dvale-økt bundet til tråden," + "og konfigurasjon tillater ikke oppretting" + "av en ikke-transaksjonell her"); service.create (ny hendelse ("fra LocalSessionFactoryBean")); }}

Denne testen viser hvordan tjenestemetoden kjøres vellykket når EventService klassen er kommentert med @Transaksjonell kommentar:

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

4. KommentarSessionFactoryBean

Dette unntaket kan også oppstå når vi bruker org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean å lage SessionFactory i vår-søknaden.

La oss se på noen eksempelkoder som demonstrerer dette. I denne grad definerer vi en Java Spring-konfigurasjonsklasse med KommentarSessionFactoryBean:

@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øktFabrikk; } // ...}

Med det samme settet med DAO-, service- og modellklasser fra forrige avsnitt, møter vi unntaket som beskrevet ovenfor:

@RunWith (SpringJUnit4ClassRunner.class) @ContextConfiguration (classes = {PersistenceConfig.class}, loader = AnnotationConfigContextLoader.class) public class HibernateExceptionScen2MainIntegrationTest {@Autowired EventService service; @Rule public ExpectedException expectEx = ExpectedException.none (); @Test offentlig ugyldig nårNoTransBoundToSession_thenException () {forventetEx.expectCause (IsInstanceOf.instanceOf (HibernateException.class)); expectEx.expectMessage ("Ingen dvale-økt bundet til tråden," + "og konfigurasjon tillater ikke oppretting" + "av en ikke-transaksjonell her"); service.create (ny hendelse ("fra AnnotationSessionFactoryBean")); }}

Hvis vi kommenterer serviceklassen med en @Transaksjonell merknad, tjenestemetoden 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; @Rule public ExpectedException expectEx = ExpectedException.none (); @Test offentlig ugyldig nårEntityIsCreated_thenNoExceptions () {service.create (ny hendelse ("fra AnnotationSessionFactoryBean")); Listehendelser = service.findAll (); }}

5. Løsningen

Det er klart at getCurrentSession () metoden for SessionFactory hentet fra våren må kalles fra en åpen transaksjon. Derfor, løsningen er å sikre at våre DAO / servicemetoder / klasser er merket riktig med @Transaksjonell kommentar.

Det bør bemerkes at i dvalemodus 4 og nyere versjoner, er meldingen om unntaket som blir kastet av samme grunn annerledes formulert. I stedet for “Ingen dvalemodus er bundet til tråden ”, vi ville få “Kunne ikke skaffe transaksjonssynkronisert økt for gjeldende tråd.

Det er et annet viktig poeng å komme med. Sammen med org.hibernate.context.CurrentSessionContext grensesnitt, har dvalemodus introdusert en eiendom hibernate.current_session_context_class som kan settes til klassen som implementerer gjeldende øktkontekst.

Som nevnt tidligere, kommer Spring med sin egen implementering av dette grensesnittet: SpringSessionContext. Som standard angir den hibernate.current_session_context_class eiendom lik denne klassen.

Som en konsekvens, hvis vi eksplisitt setter denne egenskapen til noe annet, forstyrrer det Springs evne til å administrere dvaleøkten og transaksjonene. Dette resulterer også i et unntak, men er forskjellig fra unntaket som vurderes.

Oppsummering er det viktig å huske at vi ikke skal stille inn hibernate.current_session_context_class eksplisitt når vi bruker våren til å administrere dvalemodusøkten.

6. Konklusjon

I denne artikkelen så vi på hvorfor et når unntaket org.hibernate.HibernateException: Ingen dvalemodus økt bundet til tråd blir kastet i dvalemodus 3 sammen med noen eksempler på kode og hvordan vi enkelt kan løse det.

Koden for denne artikkelen finner du på Github.

Persistensbunn

Jeg kunngjorde nettopp det nye Lær våren kurs, med fokus på det grunnleggende i vår 5 og vårstøvel 2:

>> KONTROLLER KURSET

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