2017-01-21 93 views
2

TL; DR:註釋有@Transactional(propagation = Propagation.NOT_SUPPORTED) Hibernate和TransactionRequiredException當傳播設置爲Propagation.NOT_SUPPORTED

  • 休眠5.0.4.Final

    • 服務方法:一切正常(在沒有事務執行方法)
    • 休眠5.2.5.Final:javax.persistence.TransactionRequiredException: no transaction is in progress被拋出
    • 作爲這個問題的測試用例我創建了一個簡單的maven web應用程序,並且在代碼(從舊工作項目複製粘貼)中做出的唯一更改是Hibernate版本bum p在pom.xml中

    問:

    • 什麼是執行服務方法,而如今交易的正確方法?

    代碼片段(作爲主框架Spring):

    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 
    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 
    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"; 
        } 
    
    } 
    

    堆棧跟蹤在新的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) 
    
  • 回答

    2

    好吧,嘗試不同的配置數小時後(發佈這個問題之前,SO),我終於找到了解決辦法。

    對於新的Hibernate版本,如果要執行沒有事務的方法,必須在@Transactional上聲明另一個必需參數:readOnly = true。因此,服務部的工作的例子是:

    @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(); 
        } 
    
    } 
    

    我也證實,這個工程在調試通過調用((org.hibernate.engine.transaction.internal.TransactionImpl) session.getTransaction()).isActive();這對於第一個服務方法返回true(含交易)和false第二服務方法(與傳播。不支持)。

    +0

    我的尊敬,哥們!我以爲我不會找到它。非常感謝! –

    相關問題