Spring: поймано EmptyResultDataAccessException, вызывающее откат всей транзакции

У меня есть два метода, показанных ниже.

@Transactional
public void methodA(){
    logger.trace("Executing methodA");
    methodB()
    logger.trace("Executing methodA completed");
}

public void methodB(){
    //other codes here
    try{
        staffDao.queryById(1)   //Fetch a record from database
    }catch(EmptyResultDataAccessException e){
        logger.trace("Staff does not exists")
    }
    //other codes here
}

Когда происходит EmptyResultDataAccessException в methodB() , вся транзакция, начатая methodA(), откатывается, за исключением следующего:

org.springframework.transaction.UnexpectedRollbackException: транзакция отменена, поскольку она помечена как доступная только для отката

Я знаю, что это поведение аннотации spring @Transactional по умолчанию.

В моем случае мне нужно зафиксировать транзакцию, даже если есть EmptyResultDataAccessException. Поскольку EmptyResultDataAccessException является RuntimeException, я не могу использовать атрибут noRollBackFor аннотации @Transactional.

Кто-нибудь может предложить решение?


person faizi    schedule 10.03.2017    source источник
comment
Быстрое решение может заключаться в том, чтобы сделать EmptyResultDataAccessException проверенным исключением, поскольку Spring не откатывается в случае проверенных исключений.   -  person pkoli    schedule 10.03.2017


Ответы (2)


Я еще не внимательно изучил ваш код, но если вам просто нужен способ не откатывать транзакцию для определенного исключения, вы можете отметить это в аннотации @Transactional.

@Transactional(noRollbackFor = {EmptyResultDataAccessException.class})
public void methodA(){
.
.
}

http://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/transaction/annotation/Transactional.html#noRollbackFor--

person ritesh.garg    schedule 10.03.2017

Глядя на код deleteById в SimpleJpaRepository

public void deleteById(ID id) {
    Assert.notNull(id, "The given id must not be null!");
    this.delete(this.findById(id).orElseThrow(() -> {
        return new EmptyResultDataAccessException(String.format("No %s entity with id %s exists!", this.entityInformation.getJavaType(), id), 1);
    }));
}

Я думал, что это просто удобный метод. Если мне не нужно исключение, я просто реализую его так, как мне нужно:

repo.findById(id).ifPresent(repo::delete);
person Nils El-Himoud    schedule 21.04.2020