ate和TransactionRequiredException

ate和TransactionRequiredException

本文介绍了当传播设置为Propagation.NOT_SUPPORTED时,Hibernate和TransactionRequiredException的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

@Transactional(propagation = Propagation.NOT_SUPPORTED)注释的服务方法 code
  • Hibernate 5.0.4.Final:一切按预期工作(方法在没有事务的情况下执行)
  • Hibernate 5.2.5。最后: javax.persistence.TransactionRequiredException:没有事务正在进行被抛出

  • 作为这个问题的测试用例我创建了一个简单的maven web应用程序和代码中的唯一更改(从旧的工作项目复制粘贴)是在pom.xml中的Hibernate版本bump :


    • $ b $ b


    代码片段(Spring用作主框架):

    DAO:

      @Repository 
    public class UrlDaoImpl implements UrlDao {
    $ b $ @Autowired
    private SessionFactory sessionFactory;

    @Override
    公开列表< Url> getAllUrls(){
    Session session = sessionFactory.getCurrentSession();
    Query query = session.createQuery(from Url);
    返回query.list();
    }

    }

    服务:

      @Service 
    public class UrlServiceImpl implements UrlService {
    $ b $ @Autowired $ b $ private UrlDao urlDao;


    @覆盖
    @Transactional //在新的HIBERNATE中执行此操作
    公开列表< Url> getAllUrls(){
    return urlDao.getAllUrls();
    }

    @覆盖
    @Transactional(传播= Propagation.NOT_SUPPORTED)//这用来工作,但现在抛出异常
    公开列表与LT; URL> getAllUrlsNoTxn(){
    return urlDao.getAllUrls();
    }

    }

    控制器:

      @Controller 
    公共类HomeController {
    $ b $ @Autowired
    私人UrlService urlService;

    @RequestMapping(value =/,method = RequestMethod.GET,produce =text / plain)
    public String entryPoint(){

    urlService .getAllUrls();
    System.out.println(--------------------- ok);
    返回ok;


    @RequestMapping(value =/ no-txn,method = RequestMethod.GET,produce =text / plain)
    public String entryPointNoTxn(){

    //例外情况将在以下
    urlService.getAllUrlsNoTxn();
    System.out.println(--------------------- ok no txn);
    返回ok no txn;
    }

    }

    Stacktrace for new Hibernate :

     例外

    org.springframework.web.util.NestedServletException:请求处理失败;嵌套异常是javax.persistence.TransactionRequiredException:没有事务正在进行中
    org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:982)
    org.springframework.web.servlet.FrameworkServlet。 doGet(FrameworkServlet.java:861)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:622)
    org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
    org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
    组织。 springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197)
    org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)

    根本原因

    javax.persistence.TransactionRequiredException:没有事务在进行中
    org.hibernate.internal.SessionImpl.checkTransactionNeeded(Sess org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1406)
    org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1410)
    org.hibernate.internal.SessionImpl.flush org.springframework.orm.hibernate5.SessionFactoryUtils.flush(SessionFactoryUtils.java:144)
    org.springframework.orm.hibernate5.SpringSessionSynchronization.beforeCommit(SpringSessionSynchronization.java:95)
    org.springframework.transaction。 support.TransactionSynchronizationUtils.triggerBeforeCommit(TransactionSynchronizationUtils.java:95)
    org.springframework.transaction.support.AbstractPlatformTransactionManager.triggerBeforeCommit(AbstractPlatformTransactionManager.java:932)
    org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit( AbstractPlatformTransactionManager.java:744)
    org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:730)
    org.springframework.transactio n.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:504)
    org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:292)
    org.springframework.transaction.interceptor.TransactionInterceptor。 invoke(TransactionInterceptor.java:96)
    org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:
    com.sun.proxy。$ Proxy32.getAllUrlsNT(Unknown Source)
    com.example.web.controller.HomeController.entryPointNoTxn(HomeController.java:31)
    sun.reflect。 NativeMethodAccessorImpl.invoke0(本地方法)
    sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    java.lang 。反映.Method.invoke(Method.java:498)
    org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:220)
    org.springframework.web.method.support.InvocableHandlerMethod .invokeForRequest(InvocableHandlerMethod.java:134)
    org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:116)
    org.springframework.web.servlet.mvc .method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827)
    org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738)
    org.springframework .web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
    org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:963)
    org.springframework.web .servlet.DispatcherServlet.doSer (DispatcherServlet.java:897)
    org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
    org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java: 861)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:622)
    org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
    的javax。 servlet.http.HttpServlet.service(HttpServlet.java:729)
    org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
    org.springframework.web.filter。 CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197)
    org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)


    解决方案

    好的,在尝试不同的配置几小时之后(在将这个问题发布到SO之前),我终于找到了解决方案。 b
    $ b

    对于新的Hibernate版本,有一个如果你想执行一个没有事务的方法,必须在 @Transactional 上声明其他必须的参数: readOnly = true 。所以服务部分的工作示例是:

      @Service 
    public class UrlServiceImpl implements UrlService {

    @Autowired
    私人UrlDao urlDao;


    @Override
    @Transactional
    公开列表< Url> getAllUrls(){
    return urlDao.getAllUrls();
    }

    @覆盖
    @Transactional(readOnly的=真,传播= Propagation.NOT_SUPPORTED)// ADDED READONLY参加工作,新的Hibernate VERSIONS
    公开列表与LT; URL> ; getAllUrlsNoTxn(){
    return urlDao.getAllUrls();
    }

    }

    我也证实了这一点调用((org.hibernate.engine.transaction.internal.TransactionImpl)session.getTransaction())。isActive(); 返回 true对于第二个Service方法(带有事务)和 false ,第二个Service方法(带有Propagation.NOT_SUPPORTED)。


    TL;DR:

    • Service method annotated with @Transactional(propagation = Propagation.NOT_SUPPORTED)
    • Hibernate 5.0.4.Final: everything works as expected (method is executed without transaction)
    • Hibernate 5.2.5.Final: javax.persistence.TransactionRequiredException: no transaction is in progress is thrown
    • as a testcase for this issue I created a simple maven web app and the only change made in code (copy-paste from old working project) was Hibernate version bump in pom.xml

    Question:

    • What is the proper way to execute service methods without transaction nowadays?

    Code snippets (Spring used as a main framework):

    DAO:

    @Repository
    public class UrlDaoImpl implements UrlDao {
    
        @Autowired
        private SessionFactory sessionFactory;
    
        @Override
        public List<Url> getAllUrls() {
            Session session = sessionFactory.getCurrentSession();
            Query query = session.createQuery("from Url");
            return query.list();
        }
    
    }
    

    Service:

    @Service
    public class UrlServiceImpl implements UrlService {
    
        @Autowired
        private UrlDao urlDao;
    
    
        @Override
        @Transactional // THIS WORKS IN NEW HIBERNATE
        public List<Url> getAllUrls() {
            return urlDao.getAllUrls();
        }
    
        @Override
        @Transactional(propagation = Propagation.NOT_SUPPORTED)  // THIS USED TO WORK BUT NOW THROWS EXCEPTION
        public List<Url> getAllUrlsNoTxn() {
            return urlDao.getAllUrls();
        }
    
    }
    

    Controller:

    @Controller
    public class HomeController {
    
        @Autowired
        private UrlService urlService;
    
        @RequestMapping(value = "/", method = RequestMethod.GET, produces = "text/plain")
        public String entryPoint() {
    
            urlService.getAllUrls();
            System.out.println("--------------------- ok");
            return "ok";
        }
    
        @RequestMapping(value = "/no-txn", method = RequestMethod.GET, produces = "text/plain")
        public String entryPointNoTxn() {
    
            // EXCEPTION WILL BE THROWN BELOW
            urlService.getAllUrlsNoTxn();
            System.out.println("--------------------- ok no txn");
            return "ok no txn";
        }
    
    }
    

    Stacktrace for the exception in new Hibernate:

    exception
    
    org.springframework.web.util.NestedServletException: Request processing failed; nested exception is javax.persistence.TransactionRequiredException: no transaction is in progress
        org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:982)
        org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861)
        javax.servlet.http.HttpServlet.service(HttpServlet.java:622)
        org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
        javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
        org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
        org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197)
        org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    
    root cause
    
    javax.persistence.TransactionRequiredException: no transaction is in progress
        org.hibernate.internal.SessionImpl.checkTransactionNeeded(SessionImpl.java:3439)
        org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1410)
        org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1406)
        org.springframework.orm.hibernate5.SessionFactoryUtils.flush(SessionFactoryUtils.java:144)
        org.springframework.orm.hibernate5.SpringSessionSynchronization.beforeCommit(SpringSessionSynchronization.java:95)
        org.springframework.transaction.support.TransactionSynchronizationUtils.triggerBeforeCommit(TransactionSynchronizationUtils.java:95)
        org.springframework.transaction.support.AbstractPlatformTransactionManager.triggerBeforeCommit(AbstractPlatformTransactionManager.java:932)
        org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:744)
        org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:730)
        org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:504)
        org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:292)
        org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
        org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
        org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213)
        com.sun.proxy.$Proxy32.getAllUrlsNT(Unknown Source)
        com.example.web.controller.HomeController.entryPointNoTxn(HomeController.java:31)
        sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        java.lang.reflect.Method.invoke(Method.java:498)
        org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:220)
        org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:134)
        org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:116)
        org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827)
        org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738)
        org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
        org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:963)
        org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897)
        org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
        org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861)
        javax.servlet.http.HttpServlet.service(HttpServlet.java:622)
        org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
        javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
        org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
        org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197)
        org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    
    解决方案

    Ok, after few hours of trying different configurations (before posting this question to SO), I finally found the solution.

    For new Hibernate versions there is another required parameter that must be declared on @Transactional if you want to execute a method without a transaction: readOnly = true. So the working example of the Service part is:

    @Service
    public class UrlServiceImpl implements UrlService {
    
        @Autowired
        private UrlDao urlDao;
    
    
        @Override
        @Transactional
        public List<Url> getAllUrls() {
            return urlDao.getAllUrls();
        }
    
        @Override
        @Transactional(readOnly = true, propagation = Propagation.NOT_SUPPORTED)  // ADDED READONLY TO WORK IN NEW HIBERNATE VERSIONS
        public List<Url> getAllUrlsNoTxn() {
            return urlDao.getAllUrls();
        }
    
    }
    

    I also confirmed that this works on debug by calling ((org.hibernate.engine.transaction.internal.TransactionImpl) session.getTransaction()).isActive(); which returns true for the first Service method (with transaction) and false for the second Service method (with Propagation.NOT_SUPPORTED).

    这篇关于当传播设置为Propagation.NOT_SUPPORTED时,Hibernate和TransactionRequiredException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

  • 08-04 07:03