spring3.1.3整合hibernate3.6.4,在使用hibernate getCurrentSession()方法时,总是报如下错误:
org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here
说明:如果使用openSession()是没有问题的,但是openSession()是不推荐使用的,推荐使用的是getCurrentSession(),(在hibernate4中已完全实现事务,所以spring3.1整合hibernate4时已经不提供HibernateDaoSupport,HibernateTemplete类了,只能用hibernate原始的方式用session(具体参考:http://loushi135.iteye.com/blog/1420309))
所以我们需要解决这个问题,当然由于公司项目中使用的还是hibernate3,故本文使用的是公司项目的版本
具体报错信息如下
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.cxl.demo.dao.impl.UserDaoImpl.getSession(UserDaoImpl.java:27)
at com.cxl.demo.dao.impl.UserDaoImpl.getUserByName(UserDaoImpl.java:44)
at com.cxl.demo.service.impl.UserServiceImpl.getUserByName(UserServiceImpl.java:26)
at com.cxl.demo.controller.LoginController.loginDeal(LoginController.java:28)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:219)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:132)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:100)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:604)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:565)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:923)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:852)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:882)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:789)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:710)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:269)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:188)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:213)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:174)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:117)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:108)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:174)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:874)
at org.apache.coyote.http11.Http11BaseProtocol$Http11ConnectionHandler.processConnection(Http11BaseProtocol.java:665)
at org.apache.tomcat.util.net.PoolTcpEndpoint.processSocket(PoolTcpEndpoint.java:528)
at org.apache.tomcat.util.net.LeaderFollowerWorkerThread.runIt(LeaderFollowerWorkerThread.java:81)
at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:689)
at java.lang.Thread.run(Thread.java:619)
需要配置事务,故关于事务的配置如下
<!-- 事务配置管理器 -->
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<!-- 配置事务的传播特性 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<!--定义参与事务的方法 read-only="true" 脏数据只读,提高效率-->
<tx:method name="get*" read-only="true" propagation="SUPPORTS" />
<tx:method name="query*" read-only="true" propagation="SUPPORTS" />
<tx:method name="find*" read-only="true" propagation="SUPPORTS" />
<tx:method name="load*" read-only="true" propagation="SUPPORTS" />
<tx:method name="*" propagation="REQUIRED" />
</tx:attributes>
</tx:advice>
但是依然报错,解决方案如下
1.在配置文件中配置下面的配置
<aop:config proxy-target-class="true">
<aop:advisor pointcut="execution(* com.cxl.demo..*Service.*(..))" advice-ref="txAdvice" />
</aop:config>
此时就可以了,而且这样就不需要在service层加上@Transactional了
2.另一种解决方案是基于注解驱动的配置(在applicationContext.xml)
<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true" />
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
此时需要在service层加上@Transactional
基于注解驱动的配置要注意spring的配置,如果使用项目使用的是springmvc+hibernate时,一般会有两个spring配置文件,一个是applicationContext.xml和springmvc的相关配置文件,此时需要在applicationContext.xml将Controller的注解排除掉
<!--将Controller的注解排除掉 让@Transactional( rollbackFor={Exception.class})事务管理起作用-->
<context:component-scan base-package="com.cxl.demo">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller" />
</context:component-scan>
在springmvc中将Controller的注解加入进来,并把Service注解给去掉
<context:component-scan base-package="com.cxl.demo">
<!--在主容器中(applicationContext.xml),将Controller的注解去掉,在子容器中要加上 -->
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" />
<!-- springMVC配置文件中将Service注解给去掉 -->
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Service" />
</context:component-scan>
注:事务是配置在applicationContext.xml中,不要配置在springmvc中,完毕!