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中,完毕!