首页 > 解决方案 > @Transactional noRollbackFor EmptyResultDataAccessException.class 不起作用

问题描述

我想忽略异常并无论如何提交事务。但是,每次我得到一个错误。究竟是什么问题,我该如何解决?

@Transactional( noRollbackFor = EmptyResultDataAccessException.class )
   public Foo foo( Foo foo, String barId ) {
    Foo foo = fooRepository.save(foo)
    deleteBarSilently(barId)
      return foo ;
   }


   //@Transactional( noRollbackFor = EmptyResultDataAccessException.class )
   private void deleteBarSilently( final String barId) {

      try {
         barRepository.deleteById( barId);
      } catch ( final EmptyResultDataAccessException ignored ) {
         System.out.println( ignored );
      }
   }

错误是:org.springframework.transaction.TransactionSystemException:无法提交 JPA 事务;嵌套异常是 javax.persistence.RollbackException:事务“回滚”,因为事务设置为 RollbackOnly。

异常是 EmptyResultDataAccessException

编辑:还尝试使用 try/catch 和没有和使用异常数组 @Transactional( noRollbackFor = {EmptyResultDataAccessException.class} ) 并使用完全限定的类名

没有捕获的日志

Application exception overridden by commit exception

org.springframework.dao.EmptyResultDataAccessException: No class com.bosch.bci.foundation.digitaltwin.repository.domain.ModelReference entity with id c16675da-f5ce-46b1-97e6-7eb6869940aa exists!
    at org.springframework.data.jpa.repository.support.SimpleJpaRepository.lambda$deleteById$0(SimpleJpaRepository.java:166) ~[spring-data-jpa-2.5.3.jar:2.5.3]

用 catch 记录只是

org.springframework.transaction.TransactionSystemException: Could not commit JPA transaction; nested exception is javax.persistence.RollbackException: Transaction "rolled back" because transaction was set to RollbackOnly.

标签: spring-dataspring-transactions

解决方案


noRollbackFor需要一个 Throwable 子类数组,而不是您只传递一个类 ( EmptyResultDataAccessException)

尝试更改为(注意表示数组的大括号“{”和“}”):

@Transactional( noRollbackFor = { EmptyResultDataAccessException.class })

更新

除非您全局EmptyResultDataAccessException设置.RuntimeExceptionglobalRollbackOnParticipationFailure=false

解决方案 1

第一个解决方案是实现你自己的barRepository.deleteById( barId),它不会抛出EmptyResultDataAccessException

例如

在您BarRepository创建以下方法:

@Transactional
@Modifying
@Query("DELETE FROM Bar b WHERE b.id= :id")
void customDeleteById(Long id);

并在您的deleteBarSilently删除中try catch简单地拥有:

@Transactional
private void deleteBarSilently( final Long barId) {
     barRepository.customDeleteById( barId);
}

解决方案 2

在第二个解决方案中,您可以将代码更改为以下以deleteBarSilently在事务的外部运行,foo因此当您点击它时,EmptyResultDataAccessException不会try catch发生回滚。

首先,您需要将您的方法与不同的服务分开(以便@Transactional注释工作),比如说FooServiceand BarService

食品服务

@Service
public class FooService {

    @Autowired
    private FooRepository fooRepository;

    @Autowired
    private BarService barService;

    @Transactional
    public Student foo( Foo foo, Long barId ) {
        Foo savedFoo = fooRepository.save(foo);
        barService.deleteBarSilently(barId);
        return savedFoo ;
    }
}

酒吧服务

注释@Transactional(propagation = Propagation.NOT_SUPPORTED)将导致事务暂停的方法,在事务之外执行该方法的代码,然后恢复。

@Service
public class BarService {

    @Autowired
    private BarRepository barRepository;

    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public void deleteBarSilently( final Long barId) {
        try {
            barRepository.deleteById( barId);
        } catch (EmptyResultDataAccessException exc) {
            System.out.println(exc);
        }
    }
}

推荐阅读