Java Spring MVC - 没有 Hibernate Session 绑定到线程
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18829172/
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 MVC - No Hibernate Session bound to thread
提问by user2784083
I have problem with session in hibernate:
我在休眠中遇到会话问题:
INFO: Starting ProtocolHandler ["http-bio-8080"]
2013-09-10 16:23:11 org.apache.catalina.startup.Catalina start
INFO: Server startup in 4000 ms
2013-09-10 16:23:13 org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet [appServlet] in context with path [/portal] threw exception [Request processing failed; nested exception is org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here] with root cause
org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here
at org.springframework.orm.hibernate3.SpringSessionContext.currentSession(SpringSessionContext.java:63)
at org.hibernate.impl.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:687)
at com.myportal.portal.model.HibernateDao.getSessionFactory(HibernateDao.java:31)
at com.myportal.portal.model.HibernateDao.testowa(HibernateDao.java:46)
at com.myportal.portal.controllers.HomeController.home(HomeController.java:35)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
I've read something about this problem but the solutions don't work in my case.
我已经阅读了有关此问题的内容,但解决方案在我的情况下不起作用。
My Dao class:
我的道课:
package com.myportal.portal.model;
import org.hibernate.classic.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import com.myportal.portal.entity.User;
@Repository
@Transactional(propagation=Propagation.REQUIRED)
public class HibernateDao {
@Autowired
private SessionFactory sessionFactory;
public HibernateDao()
{
}
public HibernateDao(SessionFactory sessionFactory)
{
this.sessionFactory = sessionFactory;
}
private Session getSessionFactory()
{
return sessionFactory.getCurrentSession();
}
private void setSessionFactory(SessionFactory sessionFactory)
{
this.sessionFactory = sessionFactory;
}
public void testowa()
{
User u = new User();
//SessionFactory sf = getSessionFactory();
//Session s = sf.openSession().beginTransaction()
// problem with this
Session session = getSessionFactory();
//session.save(u);
}
}
root-context.xml
根上下文.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:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!-- Root Context: defines shared resources visible to all other web components -->
<context:annotation-config/>
<tx:annotation-driven transaction-manager="transactionManager"/>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost/hibernate1"/>
<property name="username" value="root2"/>
<property name="password" value=""/>
<property name="initialSize" value="5"/>
<property name="maxActive" value="10"/>
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="packagesToScan" value="com.spoleczniak.projekt.model"/>
<property name="hibernateProperties">
<props>
<prop key="dialect">org.hibernate.dialect.MySQLInnoDBDialect</prop>
<prop key="show_sql">true</prop>
</props>
</property>
</bean>
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />
</beans>
servlet-context.xml
servlet-context.xml
<!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->
<!-- Enables the Spring MVC @Controller programming model -->
<annotation-driven />
<context:annotation-config/>
<context:component-scan base-package="com.myportal.portal" />
<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
<resources mapping="/resources/**" location="/resources/" />
<!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->
<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value=".jsp" />
</beans:bean>
I use it like this:
我像这样使用它:
@Controller
public class RegisterController {
@Autowired
private HibernateDao hibernateDao;
@RequestMapping(value="/register")
public String registerForm()
{
hibernateDao.testowa();
return "register";
}
}
How can I fix it?
我该如何解决?
I change DAO and create UserService, but error still appears :
我更改了 DAO 并创建了 UserService,但仍然出现错误:
DAO:
道:
@Repository
public class HibernateDao {
@Autowired
private SessionFactory sessionFactory;
public HibernateDao()
{
}
public HibernateDao(SessionFactory sessionFactory)
{
this.sessionFactory = sessionFactory;
}
private Session getSessionFactory()
{
return sessionFactory.getCurrentSession();
}
private void setSessionFactory(SessionFactory sessionFactory)
{
this.sessionFactory = sessionFactory;
}
public void testowa()
{
User u = new User();
//SessionFactory sf = getSessionFactory();
//Session s = sf.openSession().beginTransaction()
// problem with this
Session session = getSessionFactory();
//session.save(u);
}
}
UserService:
用户服务:
@Service
public class UserService {
@Autowired
private HibernateDao hibernateDao;
@Transactional
public void addContact()
{
hibernateDao.testowa();
}
}
Controller:
控制器:
@Controller
public class RegisterController {
@Autowired
private UserService userService;
@RequestMapping(value="/register")
public String registerForm()
{
userService.addContact();
return "register";
}
}
采纳答案by Sotirios Delimanolis
What's happening is your servlet-context.xml
is overwriting beans in your root-context.xml
because it's declaring a component-scan
for the package containing the @Repository
class. In servlet-context.xml
, you have
发生的事情是您servlet-context.xml
正在覆盖您中的 bean,root-context.xml
因为它component-scan
为包含@Repository
该类的包声明了 a 。在servlet-context.xml
,你有
<context:component-scan base-package="com.myportal.portal" />
while your HibernateDao
class is in com.myportal.portal.model
. This ApplicationContext
will create a HibernateDao
bean without transaction management, since it doesnt have <tx:annotation-driven>
. The HibernateDao
bean that is autowired in your @Controller
is this one, not the one from the root-context.xml
(which has transaction management).
当你的HibernateDao
班级在com.myportal.portal.model
. 这ApplicationContext
将创建一个没有事务管理的HibernateDao
bean ,因为它没有。在您的自动装配的bean 是这个bean,而不是来自(具有事务管理)的bean 。<tx:annotation-driven>
HibernateDao
@Controller
root-context.xml
To fix this, you will want to start by adding
要解决此问题,您需要先添加
<context:component-scan base-package="com.myportal.portal.model" />
to your root-context.xml
and removing <context:annotation-config/>
(it is redundant). You then want to modify the component-scan
in the servlet-context.xml
to something more specific that doesn't contain the package of the @Repository
classes
到您的root-context.xml
和删除<context:annotation-config/>
(这是多余的)。那么你要修改component-scan
的servlet-context.xml
更具体的东西,不包含的包@Repository
类
<context:component-scan base-package="com.myportal.portal.controllers" />
that package would contain your @Controller
classes. You also don't need the <context:annotation-config>
.
该包将包含您的@Controller
类。您也不需要<context:annotation-config>
.
回答by ElderMael
No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here
This means that there is no current transaction within that thread.
这意味着该线程中没有当前事务。
As you corrected me the class is annotated with @Transactional but I see that it does not implement an interface. It may happen that the generated proxy does not expose the annotation as happens when you annotate a controller without it implementing an interface.
正如您纠正我的那样,该类使用 @Transactional 进行了注释,但我发现它没有实现接口。可能发生的情况是,生成的代理不会像在没有实现接口的情况下注释控制器时那样公开注释。
回答by instancenow
During beans instantiation servlet-context.xml
is read and beans with @Controller
, @Service
, @Repository
are instantiated.
在 bean 实例化期间servlet-context.xml
读取并实例化带有@Controller
, @Service
,@Repository
的 bean。
Now when application-context.xml
(which has <tx:annotation-driven />
) is read the beans are already there and so doesn't get transactional behavior. Make the package in servlet-context.xml
specific to UI like controller/ Or exclude the Service, Repository package from component-scan.
现在,当application-context.xml
(有<tx:annotation-driven />
)被读取时,bean 已经存在,因此不会出现事务行为。制作servlet-context.xml
特定于 UI的包,如控制器/或从组件扫描中排除服务、存储库包。
<context:component-scan base-package="com.java.controllers"/>