6

I'd like to ignore any exceptions that occur during a delete action in spring 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
    }
}

Problem: when I run this, I'm still getting the following exception (eg if the id to be deleted does not exist anymore in database - means it may have been deleted concurrently). How could I ignore it?

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]
Jens Schauder
  • 77,657
  • 34
  • 181
  • 348
membersound
  • 81,582
  • 193
  • 585
  • 1,120

2 Answers2

1

Even if you catch the exception, the transaction manager will mark the transaction as rollbackonly, so when you commit at the end of the method you will have an TransactionSystemException exception.

The first reflex is to mark the method @Transactional(noRollbackFor=EmptyResultDataAccessException.class) but this does not solve the problem because if you take a look in SimpleJpaRepository class wil see that delete method is marked as transactional, so when the exception is thrown, this @Transactional marks your transaction as rollback only.

In my opinion, the solution is to call findOne method and then if entity exists call delete method (call delete method by entity and not by ID) :

@Tranactional
public void remove(Long id) {
    if (id != null) {
     YouEntity entity= dao.findOne(id);
     if (nonNull(entity)) {
        dao.delete(entity);
     }
    }
 }
andolsi zied
  • 3,553
  • 2
  • 32
  • 43
-1
@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();
    }
}

You have to find out how you catch Exception1, Exception2 or just use Exception with rollbackFor={Exception.class}

Why need to declare rollbackFor? by default Spring rollbacks unchecked exceptions only.

Other option: Following will also work, but without using @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();
    }
}
sura2k
  • 7,365
  • 13
  • 61
  • 80
  • @andolsizied check the spring docs + https://stackoverflow.com/questions/7125837/why-does-transaction-roll-back-on-runtimeexception-but-not-sqlexception/7125918#7125918 – sura2k Dec 08 '17 at 16:05