Spring Hibernate - Mevcut iş parçacığı için işlemle senkronize edilmiş Oturum elde edilemedi


106

Spring + hibernate ile bir uygulama oluşturdum, ancak her zaman bu hatayı alıyorum. Bu benim hazırda bekletme ile ilk uygulamam, bazı kılavuzları okudum ama bu sorunu çözemiyorum. Nerede yanlış yapıyorum

Bu benim uygulamamın kodu

ott 05, 2014 4:03:06 PM org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
Informazioni: Refreshing   org.springframework.context.support.ClassPathXmlApplicationContext@1eab16b: startup date  [Sun Oct 05 16:03:06 CEST 2014]; root of context hierarchy
ott 05, 2014 4:03:06 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
Informazioni: Loading XML bean definitions from class path resource [springConfig.xml]
ott 05, 2014 4:03:08 PM org.hibernate.annotations.common.reflection.java.JavaReflectionManager <clinit>
INFO: HCANN000001: Hibernate Commons Annotations {4.0.5.Final}
ott 05, 2014 4:03:08 PM org.hibernate.Version logVersion
INFO: HHH000412: Hibernate Core {4.3.6.Final}
ott 05, 2014 4:03:08 PM org.hibernate.cfg.Environment <clinit>
INFO: HHH000206: hibernate.properties not found
ott 05, 2014 4:03:08 PM org.hibernate.cfg.Environment buildBytecodeProvider
INFO: HHH000021: Bytecode provider name : javassist
ott 05, 2014 4:03:09 PM org.hibernate.dialect.Dialect <init>
INFO: HHH000400: Using dialect: org.hibernate.dialect.MySQL5Dialect
ott 05, 2014 4:03:09 PM org.hibernate.engine.transaction.internal.TransactionFactoryInitiator initiateService
INFO: HHH000399: Using default transaction strategy (direct JDBC transactions)
ott 05, 2014 4:03:09 PM org.hibernate.hql.internal.ast.ASTQueryTranslatorFactory <init>
INFO: HHH000397: Using ASTQueryTranslatorFactory
Exception in thread "main" org.hibernate.HibernateException: Could not obtain transaction-synchronized Session for current thread
at org.springframework.orm.hibernate4.SpringSessionContext.currentSession(SpringSessionContext.java:134)
at org.hibernate.internal.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:1014)
at coreservlets.StudentDAOImpl.create(StudentDAOImpl.java:19)
at coreservlets.MainApp.main(MainApp.java:14)

student.java

package coreservlets;

public class Student {

    private Integer id;
    private String name;
    private Integer age;

    public Integer getId(){return id;}//getId

    public void setId(Integer id){this.id=id;}//setId

    public String getName(){return name;}//getName

    public void setName(String name){this.name=name;}//setName

    public Integer getAge(){return age;}//getAge

    public void setAge(Integer age){this.age=age;}//setAge

}//Student

studentDAO.java

package coreservlets;

import org.hibernate.SessionFactory;

public interface StudentDAO {

    public void setSessionFactory(SessionFactory sessionFactory);

    public void create(String name,Integer age);

}//StudentDAO

StudentDAOImpl.java

package coreservlets;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

@Repository
public class StudentDAOImpl implements StudentDAO {

    private SessionFactory sessionFactory;

    @Autowired
    public void setSessionFactory(SessionFactory sessionFactory){
        this.sessionFactory=sessionFactory;
    }//setSessionFactory

    public void create(String name,Integer age){
        Session session=sessionFactory.getCurrentSession();
        Student student=new Student();
        student.setName(name);
        student.setAge(age);
        session.save(student);
    }//create

}//StudentDAOImpl

MainApp.java

package coreservlets;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MainApp {

    public static void main(String[] args) {

        ApplicationContext context=new ClassPathXmlApplicationContext("springConfig.xml");

        StudentDAOImpl student=(StudentDAOImpl) context.getBean("studentDAOImpl");

        student.create("Alessandro", new Integer(33));


    }//main

}//MainApp

springConfig.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd
    http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd">

<context:annotation-config/>

<context:component-scan base-package="coreservlets"/>

<bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource">
  <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
  <property name="url" value="jdbc:mysql://localhost:3306/spring_hibernate"/>
  <property name="username" value="root"/>
  <property name="password" value="password"/>
  <property name="initialSize" value="5"/>
  <property name="maxTotal" value="10"/>
</bean>

<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="hibernateProperties">
    <value>
            hibernate.dialect=org.hibernate.dialect.MySQLDialect
    </value>
</property>

</bean>

</beans>

sql

create table student
(
id integer not null auto_increment,
name varchar(20) not null,
age integer not null,
primary key(id)
);

3
DAO oluşturma yönteminize bir @Transactional eklemeyi denediniz mi?
John

1
Bir HibernateTransactionManager bildirmeyi ve yöntemi Hibernate işlemi kullanarak yapmayı unuttunuz.
JB Nizet

@itachi doğru değil sessionFactory.openSession(), işlem devre dışı bırakılacak . Çünkü aynı seans değiller. > Sınıf hizmetine @ Patrikoko @ Baharın İşlem ek açıklamasını ekleyin doğru! şu soruya bakın: stackoverflow.com/questions/15620355/… örnek:@Transactional(readOnly = true, propagation = Propagation.REQUIRED, rollbackFor = {java.lang.Exception.class})
nvnpnco

Yanıtlar:


201

Sen gerekir etkinleştirmek işlem desteği ( <tx:annotation-driven>veya @EnableTransactionManagement) ve beyantransactionManager ve içinden çalışmalıdır SessionFactory.

Sen eklemelisiniz @Transactionaliçine senin@Repository

İle @Transactionalsenin içinde @RepositorySpring sizin depoya işlem desteği uygulamak yapabiliyor.

Sizin Studentsınıf hiçbir @ javax.persistence vardır. Nasıl * ek açıklamalar @Entityo sınıf XML ile tanımlanmıştır için ben Haritalama Yapılandırma varsayıyorum.


1
Lütfen, çalışmadığı için uygulamanın kodunu yazabilir misiniz .. Bu Hibernate ile ilk başvurum
Alex

3
<Tx: annotation-drive> için ek açıklama eşdeğeri @EnableTransactionManagement
Anand Rockzz

6
Ayrıca javax.persistance.Transactional değil, org.springframework.transaction.annotation.Transactional kullandığınızdan emin olun.
imnd_neel

Şerefe dostum, bu ek açıklamayı kaçırdığıma inanamıyorum :).
Boldbayar

1
İşlemin çalışması için saatlerce denedim ve sonunda <tx: annotation-drive> yerine @EnableTransactionManagement kullandım ve her şey mükemmel çalışıyor. Sana yeterince teşekkür edemem Manuel
Abu Sulaiman

38

Aynı sorunu yaşadım, ancak hizmet katmanının bir parçası olmayan bir sınıfta. Benim durumumda, işlem yöneticisi basitçe bağlamdan getBean()yöntemle elde edildi ve sınıf, görünüm katmanına aitti - projem OpenSessionInViewtekniği kullanıyor .

sessionFactory.getCurrentSession()Yazar, bu gibi metod, aynı durum neden olmuştur. Benim için çözüm oldukça basitti.

Session session;

try {
    session = sessionFactory.getCurrentSession();
} catch (HibernateException e) {
    session = sessionFactory.openSession();
}

Eğer getCurrentSession()yöntem başarısız olur openSession()hile yapmak gerekir.


Hibernate3'ten Hibernate5'e yükseltme yaparken, kodu SessionFactoryUtils.getSession () yerine sessionFactory.getCurrentSession () olarak değiştirmem gerekiyordu. O sırada aynı hatayla karşılaştı.
user811433

2
Bu, sessionFactory.getCurrentSession();başarılı olursa oturumun kapatılmaması, ancak sessionFactory.openSession();başarılı olursa kapatılması gerektiği gibi gerçekten kötü bir davranış verir
Richard Tingle 18'17

1
Kabul ediyorum @RichardTingle. Görünüşe göre openSession istisnayı atlamak için bir hack. Bunun için atıl çözüm ne olmalı?
Praveen Shendge

@Praveen aslında yaptığım şey, Function<Session,T>"eğer bir oturumum olsaydı X yapmak için kullanırdım" anlamına gelen bir lambda kabul ettim. Daha sonra yöntem, temel hazırlığı ve (gerekirse) oturumun temel hazırlığını kaldırmayı ele alır ve yalnızca T'yi döndürür. Böylece hizmetin harici tüketicileri hiçbir zaman bir oturuma
Richard Tingle

Bu, programımı hata belirtisi olmadan çalıştırdı. Bu şekilde oluşturulmuş birden çok sorgu arasında bir işlem yapmadığım için endişeleniyorum, bu da tutarsız sonuçlar döndürme riskim olduğu anlamına mı geliyor?
Ole VV

13

Sınıf hizmetine @Transactional bahar ek açıklamasını ekleyin


3

Xyz.DAOImpl.java dosyanızda

Aşağıdaki adımları uygulayın:

// Adım-1: Oturum fabrikasını ayarlayın

@Resource(name="sessionFactory")
private SessionFactory sessionFactory;

public void setSessionFactory(SessionFactory sf)
{
    this.sessionFactory = sf;
}

// Adım-2: Geçerli oturumu almaya çalışın ve HibernateException istisnasını yakalayın.


// Adım-3: Herhangi bir HibernateException istisnası varsa, openSession almak için true.

try 
{
    //Step-2: Implementation
    session = sessionFactory.getCurrentSession();
} 
catch (HibernateException e) 
{
    //Step-3: Implementation
    session = sessionFactory.openSession();
}

Selam! Hibernate'in bunu kendi başına yapması gerekmiyor mu?
Chris

2

Bu yapılandırmayı web.xml dosyasına ekledim ve benim için iyi çalışıyor!

<filter>
    <filter-name>OpenSessionInViewFilter</filter-name>
    <filter-class>org.springframework.orm.hibernate5.support.OpenSessionInViewFilter</filter-class>
    <init-param>
        <param-name>sessionFactoryBeanName</param-name>
        <param-value>sessionFactory</param-value>
    </init-param>
    <init-param>
        <param-name>flushMode</param-name>
        <param-value>AUTO</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>OpenSessionInViewFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

Ek olarak, en çok sıralanan cevap, uygulamanın ilk çalıştırmada paniğe kapılmasını önlemek için bana ipuçları veriyor.


1
SpringMVC 4 ve Hibernate 5 kullanıyorum
何德福

2

DAO yönteminize işleme izin vermeniz gerekir. Ekle,

@Transactional(readOnly = true, propagation=Propagation.NOT_SUPPORTED)

dao yöntemleriniz üzerinden. Ve @Transactionalpaketten olmalı:

org.springframework.transaction.annotation.Transactional

1

Bu hatayı ben de aldım çünkü @Transactional not kullandığım dosyada yanlış sınıfı içe aktarıyordum

import javax.transaction.Transactional; 

Javax yerine

import org.springframework.transaction.annotation.Transactional; 

1

Benim çözümüm (Spring'i kullanarak) başarısız olan yöntemi işlemi oluşturan ve gerçekleştiren başka bir yöntemin içine koymaktı.

Bunu yapmak için önce aşağıdakileri enjekte ettim:

@Autowired
private PlatformTransactionManager transactionManager;

Ve sonunda şunu yaptı:

public void newMethod() {
    DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
    TransactionStatus transaction = transactionManager.getTransaction(definition);

    oldMethod();

    transactionManager.commit(transaction);
}

1

@Transactional =javax.transaction.Transactional. Hemen yanına koyun @Repository.


0

Yapılandırmam böyleydi. QuartzJob , Service Bean ve Dao'm vardı . her zamanki gibi LocalSessionFactoryBean (hazırda bekletme için) ve SchedulerFactoryBean for Quartz çerçevesi ile yapılandırıldı. Quartz işini yazarken yanlışlıkla @ Service ile açıklama ekledim , bunu yapmamalıydım çünkü QuartzBean'i SpringBeanJobFactory'yi genişleten AutowiringSpringBeanJobFactory'yi kullanarak bağlamak için başka bir strateji kullanıyordum .

Öyleyse gerçekte olan şuydu: Quartz Autowire nedeniyle, TX Job Bean'e enjekte ediliyordu ve aynı zamanda Tx Context @ Service notation sayesinde ayarlanıyordu ve bu nedenle TX senkronize olmuyordu !!

Umarım yukarıdaki çözümlerin sorunu gerçekten çözemeyenlere yardımcı olur. Spring 4.2.5 ve Hibernate 4.0.1 kullanıyordum,

Bu dizisindeki @ eklemek için bir gereksiz öneri olduğunu görüyoruz İşlemsel DAO (@ için açıklama Depo ), o @ işe yaramaz bir öneri nedenidir Deposu sahip olması gereken tüm ne özel olarak ayarlanmış gerekmez sahiptir @ olduğunu işlemsel üzerinde DAO'lar, @Trasancational tarafından zaten enjekte edilen hizmetlerden çağrıldığı için DAO'lar . Umarım bu, Quartz, Spring ve Hibernate'i birlikte kullanan insanlara yardımcı olabilir.


0

Ekle transaction-managersizin için <annotation-driven/>de yay servlet.xml:

<tx:annotation-driven transaction-manager="yourTransactionBeanID"/>

0

Dao sınıfınızı kontrol edin. Şöyle olmalı:

Session session = getCurrentSession();
Query query = session.createQuery(GET_ALL);

Ve ek açıklamalar:

@Transactional
@Repository

0

Aynı sorunla karşılaştım ve sonunda <tx:annotaion-driven />, [dispatcher]-servlet.xmlbileşen tarama öğesinin @serviceek açıklamalı sınıfın etkinleştirildiği yerde tanımlanmadığını öğrendim .

Basitçe <tx:annotaion-driven />bileşen tarama elemanını bir araya getirirsek sorun ortadan kalktı.


0

Benzer sorunum, 2 yaklaşımın altında çözüldü.

1) İşlemleri manuel olarak gerçekleştirerek:

Session session = sessionFactory.getCurrentSession();
Transaction tx = session.beginTransaction();
UserInfo user = (UserInfo) session.get(UserInfo.class, 1);
tx.commit();

2) Spring'e web.xmlfiltrelerinizdeki işlemleri sizin için açmasını ve yönetmesini söyleyin ve şunu kullanın @Repository @Transactional:

<filter>
  <filter-name>hibernateFilter</filter-name>
  <filter-class>org.springframework.orm.hibernate5.support.OpenSessionInViewFilter</filter-class>
  <init-param>
    <param-name>sessionFactory</param-name>
    <param-value>session.factory</param-value>
  </init-param>
</filter>
<filter-mapping>
  <filter-name>hibernateFilter</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>

0

İnsanlı yıl yorumu için teşekkürler. Springmvc kullanıyorum ve benim durumumda kullanmalıyım

@Repository
@Transactional
@EnableTransactionManagement
public class UserDao {
...
}

ve ayrıca pom.xml'ye yay bağlamı ekliyorum ve işe yarıyor


0

Ben de aynı sorunu yaşadım. Bunu aşağıdakileri yaparak çözdüm:

  1. Bu satırı dispatcher-servletdosyaya ekleyin :

    <tx:annotation-driven/>

    <beans>Aynı dosyada yukarıdaki bölümü kontrol edin . Bu iki satır mevcut olmalıdır:

    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation= "http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"
  2. Ayrıca eklediğinizden @Repositoryve @Transactionalnerede kullandığınızdan emin olun sessionFactory.

    @Repository
    @Transactional
    public class ItemDaoImpl implements ItemDao {
        @Autowired
        private SessionFactory sessionFactory;

-1

Yukarıdaki bu sınıfta @Repositorysadece bir ek açıklama daha yerleştirildi @Transactional, işe yarayacak. Çalışırsa yanıt verin ( Y/ N):

@Repository
@Transactional
public class StudentDAOImpl implements StudentDAO

1
SO'ya hoş geldiniz. Lütfen ilerleyin Nasıl iyi bir cevap yazabilirim . SO'da E / H yanıtlama geleneği yoktur. Cevabınız işaretleyecekleri kişi için işe yarıyorsa, kabul edilmiş sayılır. Faydalı bir cevap da olumlu oylanabilir.
Sri9911
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.