Spring Hibernate - 无法为当前线程获取事务同步会话
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/26203446/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Spring Hibernate - Could not obtain transaction-synchronized Session for current thread
提问by Alex
I created an application with spring + hibernate, but I always get this error. This is my first application with hibernate, I read some guides but I can not solve this problem. Where am I doing wrong?
我用 spring + hibernate 创建了一个应用程序,但我总是收到这个错误。这是我第一个使用 hibernate 的应用程序,我阅读了一些指南,但我无法解决这个问题。我哪里做错了?
This is the code of my application
这是我的应用程序的代码
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
学生.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
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
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
sql
create table student
(
id integer not null auto_increment,
name varchar(20) not null,
age integer not null,
primary key(id)
);
回答by Manuel Jordan
You must enablethe transaction support (<tx:annotation-driven>or @EnableTransactionManagement) and declarethe transactionManagerand it should work through the SessionFactory.
您必须启用的事务支持(<tx:annotation-driven>或@EnableTransactionManagement)和宣布的transactionManager,它应该通过工作SessionFactory。
You must add @Transactionalinto your @Repository
您必须添加@Transactional到您的@Repository
With @Transactionalin your @RepositorySpring is able to apply transactional support into your repository.
随着@Transactional在你的@Repository春天是能够应用的事务处理支持到你的资料库。
Your Studentclass has no the @javax.persistence.* annotations how @Entity, I am assuming the Mapping Configuration for that class has been defined through XML.
您的Student类没有@javax.persistence.* 注释@Entity,我假设该类的映射配置已通过 XML 定义。
回答by itachi
I have had the same issue, but in a class that was not a part of the service layer. In my case, the transaction manager was simply obtained from the context by the getBean()method, and the class belonged to the view layer - my project utilizes OpenSessionInViewtechnique.
我遇到了同样的问题,但在一个不属于服务层的类中。在我的例子中,事务管理器只是通过方法从上下文中获取的getBean(),并且该类属于视图层 - 我的项目利用了OpenSessionInView技术。
The sessionFactory.getCurrentSession()method, has been causing the same exception as the author's. The solution for me was rather simple.
该sessionFactory.getCurrentSession()方法引起了与作者相同的异常。对我来说,解决方案相当简单。
Session session;
try {
session = sessionFactory.getCurrentSession();
} catch (HibernateException e) {
session = sessionFactory.openSession();
}
If the getCurrentSession()method fails, the openSession()should do the trick.
如果该getCurrentSession()方法失败,则openSession()应该可以解决问题。
回答by Patrikoko
Add the annotation @Transactional of spring in the class service
在类服务中添加spring的注解@Transactional
回答by ArunDhwaj IIITH
In your xyz.DAOImpl.java
在你的 xyz.DAOImpl.java
Do the following steps:
执行以下步骤:
//Step-1: Set session factory
//第一步:设置会话工厂
@Resource(name="sessionFactory")
private SessionFactory sessionFactory;
public void setSessionFactory(SessionFactory sf)
{
this.sessionFactory = sf;
}
//Step-2: Try to get the current session, and catch the HibernateException exception.
//Step-3: If there are any HibernateException exception, then true to get openSession.
//Step-2:尝试获取当前会话,并捕获HibernateException异常。
//Step-3:如果有任何HibernateException异常,则为true获取openSession。
try
{
//Step-2: Implementation
session = sessionFactory.getCurrentSession();
}
catch (HibernateException e)
{
//Step-3: Implementation
session = sessionFactory.openSession();
}
回答by u6462197
I added these configuration in web.xml and it works well for me!
我在 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>
Additionally, the most ranked answer give me clues to prevent application from panic at the first run.
此外,排名最高的答案为我提供了防止应用程序在第一次运行时出现恐慌的线索。
回答by RahuL Sharma
You need to allow transaction to your DAO method. Add,
您需要允许交易到您的 DAO 方法。添加,
@Transactional(readOnly = true, propagation=Propagation.NOT_SUPPORTED)
over your dao methods.
And @Transactionalshould be from the package:
超过你的 dao 方法。并且@Transactional应该来自包:
org.springframework.transaction.annotation.Transactional
回答by Aliuk
My solution was (using Spring) putting the method that fails inside another method that creates and commits the transaction.
我的解决方案是(使用 Spring)将失败的方法放入另一个创建和提交事务的方法中。
To do that I first injected the following:
为此,我首先注入了以下内容:
@Autowired
private PlatformTransactionManager transactionManager;
And finally did this:
最后做到了这一点:
public void newMethod() {
DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
TransactionStatus transaction = transactionManager.getTransaction(definition);
oldMethod();
transactionManager.commit(transaction);
}
回答by Alter Hu
@Transactional =javax.transaction.Transactional. Put it just beside @Repository.
@Transactional =javax.transaction.Transactional. 把它放在旁边@Repository。
回答by browndoor
I had this error too because in the file where I used @Transactionalannotation, I was importing the wrong class
我也有这个错误,因为在我使用@Transactional注释的文件中,我导入了错误的类
import javax.transaction.Transactional;
Instead of javax, use
代替 javax,使用
import org.springframework.transaction.annotation.Transactional;
回答by SANJAY GAUTAM
My configuration was like this. I had a QuartzJob, a Service Bean , and Dao . as usual it was configured with LocalSessionFactoryBean (for hibernate) , and SchedulerFactoryBean for Quartz framework. while writing the Quartz job , I by mistake annotated it with @Service, I should not have done that because I was using another strategy to wire the QuartzBeanusing AutowiringSpringBeanJobFactoryextending SpringBeanJobFactory.
我的配置是这样的。我有一个QuartzJob、一个 Service Bean 和 Dao。像往常一样,它配置了 LocalSessionFactoryBean (用于休眠)和 SchedulerFactoryBean 用于 Quartz 框架。而写石英工作,我误用@注解它服务,我不应该这样做,因为我是用另一种策略,接线QuartzBean使用AutowiringSpringBeanJobFactory延伸SpringBeanJobFactory。
So what actually was happening is that due to Quartz Autowire , TX was getting injected to the Job Bean and at the same time Tx Context was set by virtue of @Serviceannotation and hence the TX was falling out of sync !!
所以,实际上正在发生的是,由于石英自动装配,TX渐渐注入工作豆,并在同一时间Tx背景是凭借@设置服务注解,因此TX正在下降同步进行!
I hope it help to those for whom above solutions really didn't solved the issue. I was using Spring 4.2.5 and Hibernate 4.0.1 ,
我希望它对上述解决方案确实没有解决问题的人有所帮助。我使用的是 Spring 4.2.5 和 Hibernate 4.0.1 ,
I see that in this thread there is a unnecessary suggestion to add @Transactionalannotation to the DAO(@Repository) , that is a useless suggestion cause @Repositoryhas all what it needs to have don't have to specially set that @transactionalon DAOs , as the DAOs are called from the services which have already being injected by @Trasancational. I hope this might be helpful people who are using Quartz , Spring and Hibernate together.
我看到,在这个线程是有必要的建议,以@添加事务注释到DAO(@库),这是一个无用的建议,原因@库拥有所有它所需要有根本没有专门设置@事务上DAOs,因为 DAOs 是从已经被@Trasancational注入的服务中调用的。我希望这可能对同时使用 Quartz、Spring 和 Hibernate 的人有所帮助。

