陈建华的博客
专注web开发
解决org.hibernate.TransactionException: nested transactions not supported
2016-12-02 08:45:25   阅读738次

本想用hibernate来批量的向表中插入数据。但是却遇到了如下的异常:

org.hibernate.TransactionException: nested transactions not supported
    at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.begin(AbstractTransactionImpl.java:152)
    at com.xxxx.cw.dao.impl.common.BaseDaoImpl.addBatch(BaseDaoImpl.java:82)
    at com.xxxx.cw.service.TLogStaticService.batchAddLog(TLogStaticService.java:39)
    at com.xxxx.cw.service.TLogStaticService.addLog(TLogStaticService.java:31)
    at com.xxxx.cw.service.TLogStaticService$$FastClassByCGLIB$$5b61d6ea.invoke(<generated>)
    at net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:191)
    at org.springframework.aop.framework.Cglib2AopProxy$CglibMethodInvocation.invokeJoinpoint(Cglib2AopProxy.java:689)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:110)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:90)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
    at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:622)
    at com.xxxx.cw.service.TLogStaticService$$EnhancerByCGLIB$$d71ceaa9.addLog(<generated>)
    at com.xxxx.cw.web.controller.TLogStaticController.collect(TLogStaticController.java:75)
    at sun.reflect.GeneratedMethodAccessor23.invoke(Unknown Source)
    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:637)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at com.xxxx.cw.web.controller.SystemContextFilter.doFilter(SystemContextFilter.java:58)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:291)
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:859)
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:602)
    at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
    at java.lang.Thread.run(Thread.java:619)

我的代码为:

public void addUploadFile(UploadedFile uploadedFile) throws Exception{
    Session session=su.getCurrentSession();
    Transaction ts=session.beginTransaction();
    try {
        session.save(uploadedFile);
    } catch (Exception e) {
    // TODO: handle exception
        ts.rollback();
        e.printStackTrace(); 
        throw e;
    }
}

修改为正确的代码为:

public void addUploadFile(UploadedFile uploadedFile) throws Exception{
    Session session=su.openSession();//此处有改动
    Transaction ts=session.beginTransaction();
    try {
        session.save(uploadedFile);
    } catch (Exception e) {
    // TODO: handle exception
        ts.rollback();
        e.printStackTrace(); 
        throw e;
    }
}

对比代码,应该能看到su为sessionFactory,使用hibernate的事务,获取session的错误做法为sessionFactory.getCurrentSession()。正确做法为sessionFactory.openSession()。

分析:getCurrentSession这个session可能是hibernate自己专用或者给spring专用的。事务缓存等等的,由框架直接来使用。而如果我们要专用session,就直接重新打开一个session就可以了。

这样改,解决了我的问题。


附:

查询此问题中,还有一种情况经常被大家忽视。

就是session.beginTransaction();这个获取的Transaction已经是begin的了,就不需要再去执行一次begin了。

如果非要用begin,那么就不要用beginTransaction了,而是用session.getTransaction()来获取,这样的事务,是没有begin的,需要自己去begin。

1.openSession和getCurrentSession的区别?

   *openSession必须关闭,currentSession在事务结束后自动关闭

   *openSession没有和当前线程绑定,currentSession和当前线程绑定

2.如果使用currentSession需要在hibernate.cfg.xml文件中进行配置:

   *如果是本地事务(jdbc事务)

     <propertyname="hibernate.current_session_context_class">thread</property>

   *如果是全局事务(jta事务)

   <propertyname="hibernate.current_session_context_class">jta</property>

全局事务:资源管理器管理和协调的事务,可以跨越多个数据库和进程。资源管理器一般使用XA 二阶段提交协议与“企业信息系统”(EIS) 或数据库进行交互。 

本地事务:在单个 EIS或数据库的本地并且限制在单个进程内的事务。本地事务不涉及多个数据来源。

(完)



-----------------------------------------------------
转载请注明来源此处
原地址:#

-----网友评论----
暂无评论
-----发表评论----
微网聚博客乐园 ©2014 blog.mn886.net 鲁ICP备14012923号   网站导航