HibernateException: Nincs hibernált munkamenet kötve a szálhoz a Hibernate 3-ban

Kitartás felső

Most jelentettem be az újat Tanulj tavaszt tanfolyam, amelynek középpontjában az 5. tavasz és a tavaszi bakancs 2 alapjai állnak:

>> ELLENŐRIZZE A FOLYAMATOT

1. Bemutatkozás

Ebben a rövid bemutatóban tisztázni fogjuk, hogy a „Nincs-e hibernált munkamenet kötve a szálra” kivétel és hogyan lehet ezt megoldani.

Itt két különböző forgatókönyvre fogunk összpontosítani:

  1. használni a LocalSessionFactoryBean
  2. használni a AnnotationSessionFactoryBean

2. Az ok

A 3-as verzióval Hibernate bevezette a kontextusos munkamenet és a getCurrentSession () módszert adtak a SessionFactory osztály. A kontextuális munkamenetről itt található további információ.

A tavasznak saját megvalósítása van a org.hibernate.context.CurrentSessionContext interfész - org.springframework.orm.hibernate3.SpringSessionContext (a Spring Hibernate 3 esetében). Ehhez a munkamenethez tranzakcióhoz kell kötni.

Természetesen olyan osztályok, amelyek hívnak getCurrentSession () metódussal kell kiegészíteni @ Tranzakció akár osztály szintjén, akár módszer szinten. Ha nem, akkor a org.hibernate.HibernateException: Nincs hibernált munkamenet kötve a szálhoz dobni fogják.

Vessünk egy gyors pillantást egy példára.

3. LocalFactorySessionBean

Ő az első forgatókönyv, amelyet ebben a cikkben megvizsgálnánk.

A Java Spring konfigurációs osztályt definiáljuk LocalSessionFactoryBean:

@Configuration @EnableTransactionManagement @PropertySource ({"classpath: persistence-h2.properties"}) @ComponentScan ({"com.baeldung.persistence.dao", "com.baeldung.persistence.service"}) public class PersistenceConfigHibernate3 {// ... @Bean public LocalSessionFactoryBean sessionFactory () {LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean (); Erőforrás config = új ClassPathResource ("kivételDemo.cfg.xml"); sessionFactory.setDataSource (dataSource ()); sessionFactory.setConfigLocation (config); sessionFactory.setHibernateProperties (hibernateProperties ()); return sessionFactory; } // ...}

Ne feledje, hogy hibernált konfigurációs fájlt (kivételDemo.cfg.xml) itt a modellosztály feltérképezése érdekében. Ez azért van, mert a org.springframework.orm.hibernate3.LocalSessionFactoryBean nem biztosítja az ingatlant packageToScan, modellosztályok feltérképezéséhez.

Íme az egyszerű szolgáltatásunk:

@Service @Transactional public class EventService {@Autowired private IEventDao dao; public void create (Esemény entitás) {dao.create (entitás); }}
@Entity @Table (name = "EVENTS") public class Esemény megvalósítja a Serializable {@Id @GeneratedValue private Long azonosítót; privát karakterlánc leírása; // ...}

Amint az alábbi kódrészletből láthatjuk, a getCurrentSession () módszere SessionFactory osztály a hibernált munkamenet megszerzésére szolgál:

public absztrakt osztály AbstractHibernateDao megvalósítja az IOperations {private Class clazz; @Autowired private SessionFactory sessionFactory; // ... @Orride public void create (T entitás) {Preconditions.checkNotNull (entitás); getCurrentSession (). persist (entitás); } védett munkamenet getCurrentSession () {return sessionFactory.getCurrentSession (); }}

Az alábbi teszt sikeresen teljesíti, bemutatva, hogy miként dobják meg a kivételt, amikor az osztály EventService A szolgáltatási módszert tartalmazó elemet nem jegyzik fel a @ Tranzakció kommentár:

@RunWith (SpringJUnit4ClassRunner.class) @ContextConfiguration (class = {PersistenceConfigHibernate3.class}, loader = AnnotationConfigContextLoader.class) public class HibernateExceptionScen1MainIntegrationTest {@Autowired Event; @Rule public ExpectedException expectedEx = ExpectedException.none (); @Test public void whenNoTransBoundToSession_thenException () {várhatóEx.expectCause (IsInstanceOf.instanceOf (HibernateException.class)); VárhatóEx.expectMessage ("Nincs hibernált munkamenet kötve a szálhoz, a" + "és a konfiguráció nem teszi lehetővé a nem tranzakciós" + "létrehozását itt"); service.create (new Event ("from LocalSessionFactoryBean")); }}

Ez a teszt megmutatja, hogy a szolgáltatási módszer hogyan teljesül sikeresen, amikor a EventService osztályt a @ Tranzakció kommentár:

@RunWith (SpringJUnit4ClassRunner.class) @ContextConfiguration (class = {PersistenceConfigHibernate3.class}, loader = AnnotationConfigContextLoader.class) public class HibernateExceptionScen1MainIntegrationTest {@Autowired Event; @Rule public ExpectedException expectedEx = ExpectedException.none (); @Test public void whenEntityIsCreated_thenNoExceptions () {service.create (new Event ("from LocalSessionFactoryBean")); List események = service.findAll (); }}

4. AnnotationSessionFactoryBean

Ez a kivétel akkor is előfordulhat, ha a org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean hogy létrehozza a SessionFactory tavaszi alkalmazásunkban.

Nézzünk meg néhány mintakódot, amely ezt demonstrálja. Ennyire meghatározunk egy Java Spring konfigurációs osztályt a AnnotationSessionFactoryBean:

@Configuration @EnableTransactionManagement @PropertySource ({"classpath: persistence-h2.properties"}) @ComponentScan ({"com.baeldung.persistence.dao", "com.baeldung.persistence.service"}) public class PersistenceConfig {// ... @Bean public AnnotationSessionFactoryBean sessionFactory () {AnnotationSessionFactoryBean sessionFactory = new AnnotationSessionFactoryBean (); sessionFactory.setDataSource (dataSource ()); sessionFactory.setPackagesToScan (új karakterlánc [] {"com.baeldung.persistence.model"}); sessionFactory.setHibernateProperties (hibernateProperties ()); return sessionFactory; } // ...}

Az előző szakaszban szereplő DAO, Service és Model osztályok ugyanazzal a készletével találkozunk a fent leírt kivétellel:

@RunWith (SpringJUnit4ClassRunner.class) @ContextConfiguration (class = {PersistenceConfig.class}, loader = AnnotationConfigContextLoader.class) public class HibernateExceptionScen2MainIntegrationTest {@Autowired EventService service; @Rule public ExpectedException expectedEx = ExpectedException.none (); @Test public void whenNoTransBoundToSession_thenException () {várhatóEx.expectCause (IsInstanceOf.instanceOf (HibernateException.class)); VárhatóEx.expectMessage ("Nincs hibernált munkamenet kötve a szálhoz, a" + "és a konfiguráció nem teszi lehetővé a nem tranzakciós" + "létrehozását itt"); service.create (new Event ("from AnnotationSessionFactoryBean")); }}

Ha a szolgáltatási osztályt a-val jegyezzük fel @ Tranzakció megjegyzéssel, a kiszolgálás módja a várakozásoknak megfelelően működik, és az alább látható teszt sikeres:

@RunWith (SpringJUnit4ClassRunner.class) @ContextConfiguration (class = {PersistenceConfig.class}, loader = AnnotationConfigContextLoader.class) public class HibernateExceptionScen2MainIntegrationTest {@Autowired EventService service; @Rule public ExpectedException expectedEx = ExpectedException.none (); @Test public void whenEntityIsCreated_thenNoExceptions () {service.create (new Event ("from AnnotationSessionFactoryBean")); List események = service.findAll (); }}

5. A megoldás

Világos, hogy a getCurrentSession () módszere SessionFactory a Spring-től kapott ügyleteket nyílt tranzakción belül kell behívni. Ebből kifolyólag, a megoldás az, hogy biztosítsuk, hogy a DAO / Service módszereinket / osztályainkat a @ Tranzakció annotáció.

Meg kell jegyezni, hogy a Hibernate 4 és újabb verzióiban az ugyanezen okból kivetett kivétel üzenete másképp van megfogalmazva. A „Nincs hibernált munkamenet kötve a szálhoz ”, kapnánkNem sikerült megszerezni a tranzakcióval szinkronizált munkamenetet az aktuális szálhoz.

Van még egy fontos szempont. Együtt a org.hibernate.context.CurrentSessionContext felületen a Hibernate bemutatott egy tulajdonságot hibernate.current_session_context_class amely beállítható az aktuális munkamenet-kontextust megvalósító osztályra.

Mint korábban említettük, a Spring saját kezűleg valósítja meg ezt a felületet: SpringSessionContext. Alapértelmezés szerint a hibernate.current_session_context_class az osztálynak megfelelő tulajdonság.

Következésképpen, ha ezt a tulajdonságot kifejezetten valami másra állítjuk, ez megzavarja Spring képességét a hibernált munkamenet és tranzakciók kezelésére. Ez szintén kivételt eredményez, de eltér a vizsgált kivételtől.

Összegezve fontos megjegyezni, hogy nem szabad beállítanunk a hibernate.current_session_context_class kifejezetten akkor, amikor a Spring funkciót használjuk a hibernált munkamenet kezeléséhez.

6. Következtetés

Ebben a cikkben megvizsgáltuk, miért és mikor kivétel org.hibernate.HibernateException: Nincs hibernált munkamenet kötve a szálhoz a Hibernate 3-ba dobódik, néhány példakóddal együtt, és azzal, hogy hogyan oldhatjuk meg könnyen.

A cikk kódja a Github oldalon található.

Perzisztencia alsó

Most jelentettem be az újat Tanulj tavaszt tanfolyam, amelynek középpontjában az 5. tavasz és a tavaszi bakancs 2 alapjai állnak:

>> ELLENŐRIZZE A FOLYAMATOT