当前位置:  开发笔记 > 编程语言 > 正文

当传播设置为Propagation.NOT_SUPPORTED时,Hibernate和TransactionRequiredException

如何解决《当传播设置为Propagation.NOT_SUPPORTED时,Hibernate和TransactionRequiredException》经验,为你挑选了1个好方法。

TL; DR:

用注释的服务方法 @Transactional(propagation = Propagation.NOT_SUPPORTED)

Hibernate 5.0.4.Final:一切都按预期工作(方法在没有事务的情况下执行)

Hibernate 5.2.5.Final:javax.persistence.TransactionRequiredException: no transaction is in progress被抛出

作为这个问题的测试用例,我创建了一个简单的maven Web应用程序,并且代码中唯一的更改(来自旧工作项目的复制粘贴)是pom.xml中的Hibernate版本

题:

现在如何在没有交易的情况下执行服务方法的正确方法是什么?

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

DAO:

@Repository
public class UrlDaoImpl implements UrlDao {

    @Autowired
    private SessionFactory sessionFactory;

    @Override
    public List 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 getAllUrls() {
        return urlDao.getAllUrls();
    }

    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)  // THIS USED TO WORK BUT NOW THROWS EXCEPTION
    public List 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";
    }

}

Stacktrace用于新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)

dominik.. 5

好的,经过几个小时尝试不同的配置(在将此问题发布到SO之前),我终于找到了解决方案.

对于新的Hibernate版本,@Transactional如果要在没有事务的情况下执行方法,则必须声明另一个必需参数:readOnly = true.因此,服务部分的工作示例是:

@Service
public class UrlServiceImpl implements UrlService {

    @Autowired
    private UrlDao urlDao;


    @Override
    @Transactional
    public List getAllUrls() {
        return urlDao.getAllUrls();
    }

    @Override
    @Transactional(readOnly = true, propagation = Propagation.NOT_SUPPORTED)  // ADDED READONLY TO WORK IN NEW HIBERNATE VERSIONS
    public List getAllUrlsNoTxn() {
        return urlDao.getAllUrls();
    }

}

我还确认这可以通过调用第一个Service方法(带事务)和第二个Service方法(带Propagation.NOT_SUPPORTED)的((org.hibernate.engine.transaction.internal.TransactionImpl) session.getTransaction()).isActive();返回true来进行调试false.



1> dominik..:

好的,经过几个小时尝试不同的配置(在将此问题发布到SO之前),我终于找到了解决方案.

对于新的Hibernate版本,@Transactional如果要在没有事务的情况下执行方法,则必须声明另一个必需参数:readOnly = true.因此,服务部分的工作示例是:

@Service
public class UrlServiceImpl implements UrlService {

    @Autowired
    private UrlDao urlDao;


    @Override
    @Transactional
    public List getAllUrls() {
        return urlDao.getAllUrls();
    }

    @Override
    @Transactional(readOnly = true, propagation = Propagation.NOT_SUPPORTED)  // ADDED READONLY TO WORK IN NEW HIBERNATE VERSIONS
    public List getAllUrlsNoTxn() {
        return urlDao.getAllUrls();
    }

}

我还确认这可以通过调用第一个Service方法(带事务)和第二个Service方法(带Propagation.NOT_SUPPORTED)的((org.hibernate.engine.transaction.internal.TransactionImpl) session.getTransaction()).isActive();返回true来进行调试false.

推荐阅读
手机用户2502852037
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有