Spring Hibernate-현재 스레드에 대한 트랜잭션 동기화 세션을 가져올 수 없습니다.


106

스프링 + 최대 절전 모드로 응용 프로그램을 만들었지 만 항상이 오류가 발생합니다. 이것은 최대 절전 모드를 사용하는 첫 번째 응용 프로그램입니다. 일부 가이드를 읽었지만이 문제를 해결할 수 없습니다. 내가 어디에서 잘못하고 있습니까?

이것은 내 응용 프로그램의 코드입니다.

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 생성 메소드에 @Transactional을 추가해 보셨습니까?
John

1
HibernateTransactionManager를 선언하고 Hibernate 트랜잭션을 사용하여 메소드를 만드는 것을 잊었습니다.
JB Nizet 2014 년

@itachi가 올바르지 않으면 sessionFactory.openSession()트랜잭션이 비활성화됩니다. 같은 세션이 아니기 때문입니다. > @Patrikoko 클래스 서비스에서 스프링의 @Transactional 주석을 추가하십시오. 이 질문을 참조하십시오 : stackoverflow.com/questions/15620355/… 예 :@Transactional(readOnly = true, propagation = Propagation.REQUIRED, rollbackFor = {java.lang.Exception.class})
nvnpnco

답변:


200

당신은 있어야합니다 수 있도록 트랜잭션 지원 ( <tx:annotation-driven>또는 @EnableTransactionManagement)와 선언transactionManager하고 그것을 통해 작동합니다 SessionFactory.

당신은 @Transactional당신의@Repository

으로 @Transactional당신의 @Repository봄 저장소에 트랜잭션 지원을 적용 할 수 있습니다.

귀하의 Student클래스에는 @ javax.persistence. * 주석이 없습니다. @Entity해당 클래스에 대한 매핑 구성이 XML을 통해 정의되었다고 가정합니다.


1
제발, 응용 프로그램이 작동하지 않기 때문에 코드를 작성해 주시겠습니까 .. 이것은 Hibernate를 사용한 첫 번째 응용 프로그램입니다
Alex

3
의 주석과 동등한 <TX : 주석 중심이> @EnableTransactionManagement입니다
아난드 Rockzz

5
또한 javax.persistance.Transactional이 아닌 org.springframework.transaction.annotation.Transactional을 사용해야합니다.
imnd_neel

건배 메이트, 나는이 주석을 놓친 것을 믿을 수 없다 :).
Boldbayar

1
나는 트랜잭션이 작동하도록 몇 시간 동안 노력했으며 마침내 <tx : annotation-driven> 대신 @EnableTransactionManagement를 사용했으며 모든 것이 완벽하게 작동합니다. 나는 당신에게 충분한 마누엘 감사 할 수
아부 술레이 만에게

38

나는 동일한 문제가 있었지만 서비스 계층의 일부가 아닌 클래스에서 발생했습니다. 필자의 경우 트랜잭션 관리자는 getBean()메서드에 의해 컨텍스트에서 간단히 얻었 으며 클래스는 뷰 레이어에 속했습니다 OpenSessionInView. 제 프로젝트는 기술을 사용 합니다.

sessionFactory.getCurrentSession()방법은 저자와 동일한 예외를 발생 시켰습니다. 나를위한 해결책은 다소 간단했습니다.

Session session;

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

는 IF getCurrentSession()방법은 실패의이 openSession()트릭을 할해야합니다.


Hibernate3에서 Hibernate5로 업그레이드 할 때, 코드를 SessionFactoryUtils.getSession ()에서 sessionFactory.getCurrentSession ()으로 변경해야했습니다. 그 당시 동일한 오류가 발생했습니다.
user811433 jul.

2
이 경우 그 정말로 불쾌한 행동을 제공 sessionFactory.getCurrentSession();한 후 성공 세션이 종료되지 않아야을하지만 경우에 sessionFactory.openSession();성공 그것은 닫아야합니다
리처드 설렘

1
@RichardTingle에 동의합니다. openSession은 예외를 우회하는 해킹 인 것 같습니다. 이를위한 유휴 솔루션은 무엇입니까?
Praveen Shendge

@Praveen 내가 실제로 한 일은 서비스가 람다를 받아들이는 Function<Session,T>것이 었습니다. "만약 내가 세션이 있다면 X를하기 위해 사용할 것"이라는 뜻입니다. 그런 방법 핸들 프로비저닝 및 (neccissary 경우) 세션을 프로비저닝 해제하고 서비스의 외부 소비자가 실제로 세션에 손을 결코 그래서 단지 T.을 반환
리처드 설렘

이로 인해 내 프로그램이 오류없이 실행되었습니다. 이런 방식으로 생성 된 여러 쿼리에서 트랜잭션이 발생하지 않을까 걱정됩니다. 즉, 일관성없는 결과를 반환 할 위험이 있습니까?
Ole VV


3

xyz.DAOImpl.java에서

다음 단계를 수행하십시오.

// 1 단계 : 세션 팩토리 설정

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

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

// 2 단계 : 현재 세션을 가져오고 HibernateException 예외를 포착합니다.


// 3 단계 : HibernateException 예외가 있으면 true로 설정하여 openSession을 가져옵니다.

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

안녕하세요! Hibernate는 그 자체로 그렇게해야하지 않습니까?
Chris

2

web.xml에 이러한 구성을 추가했으며 저에게 잘 작동합니다!

<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>

또한 가장 순위가 높은 답변은 첫 번째 실행시 응용 프로그램이 패닉 상태가되는 것을 방지하는 단서를 제공합니다.


1
나는 springMVC 4 및 최대 절전 모드 5 사용하고
何德福

2

DAO 방식으로 거래를 허용해야합니다. 더하다,

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

당신의 dao 방법에. 그리고 @Transactional패키지에서해야한다 :

org.springframework.transaction.annotation.Transactional

1

@Transactional 주석을 사용한 파일에서 잘못된 클래스를 가져 왔기 때문에이 오류가 발생했습니다.

import javax.transaction.Transactional; 

javax 대신

import org.springframework.transaction.annotation.Transactional; 

1

내 솔루션은 (Spring을 사용하여) 트랜잭션을 생성하고 커밋하는 다른 메서드 안에 실패한 메서드를 넣는 것입니다.

이를 위해 먼저 다음을 주입했습니다.

@Autowired
private PlatformTransactionManager transactionManager;

그리고 마침내 이렇게했습니다.

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

    oldMethod();

    transactionManager.commit(transaction);
}

1

@Transactional =javax.transaction.Transactional. 바로 옆에 두십시오 @Repository.


0

내 구성은 이와 같았습니다. 나는했다 QuartzJob , 서비스 콩, 그리고 다오. 평소와 같이 LocalSessionFactoryBean (최대 절전 모드 용) 및 Quartz 프레임 워크 용 SchedulerFactoryBean으로 구성되었습니다. 쿼츠 작업을 쓰는 동안, 실수로 내가 @ 그것을 주석 서비스 , 나는 다른 전략을 사용했기 때문에 와이어 것을하지 말았어야 QuartzBean을 사용하여 AutowiringSpringBeanJobFactory 확장 SpringBeanJobFactory을 .

그래서 실제로 일어난 일은 Quartz Autowire로 인해 TX가 Job Bean에 주입되고 동시에 Tx Context가 @ Service 주석 으로 설정되어 TX가 동기화되지 않은 것입니다!

위의 솔루션으로 문제가 실제로 해결되지 않은 사람들에게 도움이되기를 바랍니다. 나는 Spring 4.2.5와 Hibernate 4.0.1을 사용하고 있었다.

이 스레드에서 @ Transactional 주석을 DAO (@ Repository ) 에 추가하라는 불필요한 제안이 있음을 알 수 있습니다. 이는 @ Repository 가 @ transactional 을 특별히 설정할 필요가 없는 모든 것을 가지고 있기 때문에 쓸모없는 제안 입니다. DAO는 @Trasancational에 의해 이미 주입 된 서비스에서 호출되므로 DAO가 호출됩니다 . Quartz, Spring 및 Hibernate를 함께 사용하는 사람들에게 도움이되기를 바랍니다.


0

추가 transaction-manager귀하에 <annotation-driven/>에서의 봄-servlet.xml에 :

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

0

당신의 dao 클래스를 확인하십시오. 다음과 같아야합니다.

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

그리고 주석 :

@Transactional
@Repository

0

동일한 문제가 발생하여 마침내 컴포넌트 스캔 요소가 주석이 달린 클래스를 활성화 <tx:annotaion-driven />[dispatcher]-servlet.xml곳에 정의되지 않았다는 것을 알게되었습니다 @service.

<tx:annotaion-driven />구성 요소 스캔 요소를 결합하기 만하면 문제가 사라졌습니다.


0

내 비슷한 문제는 아래 두 가지 접근 방식으로 해결되었습니다.

1) 수동 처리 트랜잭션을 통해 :

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

2) Spring에 web.xml필터 에서 트랜잭션을 열고 관리 하도록 지시하고 다음을 사용하십시오 @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

mannedear의 코멘트 감사합니다. 나는 springmvc를 사용하고 내 경우에는 다음과 같이 사용해야합니다.

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

또한 pom.xml에 spring-context를 추가하면 작동합니다.


0

나는 같은 문제가 있었다. 다음을 수행하여 해결했습니다.

  1. 다음 행을 dispatcher-servlet파일에 추가 하십시오.

    <tx:annotation-driven/>

    <beans>동일한 파일에서 위 섹션을 확인하십시오 . 다음 두 줄이 있어야합니다.

    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. 또한 추가 @Repository하고 @Transactional어디에 사용 하고 있는지 확인하십시오 sessionFactory.

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

-1

위의 클래스에서 @Repository하나 이상의 주석을 배치 @Transactional하면 작동합니다. 작동하는 경우 회신 ( Y/ N) :

@Repository
@Transactional
public class StudentDAOImpl implements StudentDAO

1
SO에 오신 것을 환영합니다. 좋은 답변어떻게 작성합니까?를 참조하십시오 . 그래서 Y / N에 응답하는 관습이 없습니다. 당신의 대답이 그 사람에게 효과가 있다면 그들은 수락 된 것으로 표시 할 것입니다. 유용한 답변도 찬성 될 수 있습니다.
Sri9911
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.