zoukankan      html  css  js  c++  java
  • 解决Could not commit JPA transaction RollbackException: Transaction marked as rollbackOnly

    项目测试发生问题,方法正常结束,但是报了

    Could not commit JPA transaction; nested exception is javax.persistence.RollbackException: Transaction marked as rollbackOnly org.springframework.transaction.TransactionSystemException: Could not commit JPA transaction; nested exception is javax.persistence.RollbackException: Transaction marked as rollbackOnly
        at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:521)
        at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:754)
        at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:723)
        at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:393)
        at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:120)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
        at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:622)

    错误,问什么不能提交呢?

    经过查找发现了这么一段话

    I finally understood the problem:
    
    methodA() {
        methodB()
    }
    
    @Transactional(noRollbackFor = Exception.class)
    methodB() {
        ...
        try {
            methodC()
        } catch (...) {...}
        log("OK");
    }
    
    @Transactional
    methodC() {
        throw new ...();
    }
    What happens is that even though the methodB has the right annotation, the methodC does not. When the exception is thrown, the second @Transactional marks the first transaction as Rollback only anyway.

    原来,在一个transactional中如果有另一transaction发生了异常,即使你捕捉了这个异常,那么Transaction也会被定义成RollbackOnly,这也正是事务管理的原则,可是我的系统哪里出异常了呢?

    原来,spring jpa JpaRepository的实现方法中用ID删除的源码是这样的

    @Transactional
        public void delete(ID id) {
    
            Assert.notNull(id, ID_MUST_NOT_BE_NULL);
    
            T entity = findOne(id);
    
            if (entity == null) {
                throw new EmptyResultDataAccessException(String.format("No %s entity with id %s exists!",
                        entityInformation.getJavaType(), id), 1);
            }
    
            delete(entity);
        }

    他是这样实现的,先查找这个ID的对象看是否存在如果不存在则直接抛出一个非检查型异常,就不再执行delete操作。这和我平常习惯认为的不太一样,一般我习惯删除没有的记录不会报错,执行sql也是这样的。而我只是在外面捕捉了这个异常,所以发生的这样的问题。

  • 相关阅读:
    自己的文件管理软件,想怎样分类管理就怎样分类
    给博客园发展支点招
    看看自己存在哪些的个人知识管理问题和烦恼呢?
    2008年个人知识管理软件测评[草稿]
    獲取某天是星期幾
    創建鏈接服務器
    在.NET中调用Oracle9i存储过程经验总结
    C#转换成VB.net或vb.net转换成C#
    話說我們家姚明
    解决winxp搜索不到文件的问题!
  • 原文地址:https://www.cnblogs.com/fashflying/p/5669228.html
Copyright © 2011-2022 走看看