【问题标题】:How to ignore exceptions on delete if database id not exists anymore?如果数据库 id 不再存在,如何忽略删除异常?
【发布时间】:2016-10-16 11:54:18
【问题描述】:

我想忽略春季删除操作期间发生的任何异常CrudRepository

@Tranactional
public void remove(Long id) {
    try {
        if (id != null) dao.delete(id); //CrudRepository
    } catch (Exception e) {
        //ignore any exceptions, it's not critical delete
    }
}

问题:当我运行它时,我仍然收到以下异常(例如,如果要删除的 id 在数据库中不再存在 - 意味着它可能已被同时删除)。我怎么能忽略它?

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:526) ~[spring-orm-4.2.6.RELEASE.jar:4.2.6.RELEASE]
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:761) ~[spring-tx-4.2.6.RELEASE.jar:4.2.6.RELEASE]
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:730) ~[spring-tx-4.2.6.RELEASE.jar:4.2.6.RELEASE]
    at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:485) ~[spring-tx-4.2.6.RELEASE.jar:4.2.6.RELEASE]
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:291) ~[spring-tx-4.2.6.RELEASE.jar:4.2.6.RELEASE]
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96) ~[spring-tx-4.2.6.RELEASE.jar:4.2.6.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.2.6.RELEASE.jar:4.2.6.RELEASE]
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:655) ~[spring-aop-4.2.6.RELEASE.jar:4.2.6.RELEASE]

【问题讨论】:

  • 在删除操作期间不会发生此异常。您列出的代码不会引发您发布的异常。
  • 嗯,但是日志正好指向 dao.delete() 所在的代码行。

标签: java spring spring-data-jpa spring-transactions


【解决方案1】:

即使你捕获了异常,事务管理器也会将该事务标记为rollbackonly,所以当你在方法结束时提交时,你会得到一个TransactionSystemException 异常。

第一个反射是标记方法@Transactional(noRollbackFor=EmptyResultDataAccessException.class),但这并不能解决问题,因为如果你查看SimpleJpaRepository类会看到delete方法被标记为transactional,所以当异常被抛出,这个@Transactional 将您的事务标记为仅回滚。

在我看来,解决方案是调用findOne 方法,然后如果实体存在调用delete 方法(通过实体而不是ID 调用删除方法):

@Tranactional
public void remove(Long id) {
    if (id != null) {
     YouEntity entity= dao.findOne(id);
     if (nonNull(entity)) {
        dao.delete(entity);
     }
    }
 }

【讨论】:

    【解决方案2】:
    @Tranactional(rollbackFor={TableNotFoundException1.class, RecordNotFoundException.class}
    public void remove(Long id) {
        try {
            if (id != null) dao.delete(id); //CrudRepository
        } catch (Exception1 e) {
            throw new TableNotFoundException1();
        }catch (Exception2 e) {
            throw new RecordNotFoundException();
        }catch (Exception e) {
            throw new RecordNotFoundException();
        }
    }
    

    你必须找出你是如何捕捉到Exception1Exception2 或者只是使用ExceptionrollbackFor={Exception.class}

    为什么需要声明rollbackFor?默认情况下,Spring 仅回滚未经检查的异常。

    其他选项: 以下也可以,但不使用@Tranactional

    //@Tranactional(rollbackFor={TableNotFoundException1.class, RecordNotFoundException.class}
    public void remove(Long id) {
        try {
            if (id != null) dao.delete(id); //CrudRepository
        }catch (Exception e) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        }
    }
    

    【讨论】:

    猜你喜欢
    • 2021-11-28
    • 2014-01-01
    • 1970-01-01
    • 2017-11-27
    • 2019-11-17
    • 1970-01-01
    • 2023-03-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多