Spring @Transactional - 如何避免回滚特定异常?

时间:2017-08-09 13:45:11

标签: spring spring-boot

我有以下方法:

@Override
@Transactional(propagation = Propagation.REQUIRES_NEW, isolation = Isolation.SERIALIZABLE)
public void applyLog(int codFilial, List<LogLojaCentralCompactoEntity> items) {
}

内部调用:

@Override
@Transactional(noRollbackFor = PersistenceException.class)
public void apply(LogCompactoEntity entity) {
}

第二种方法有一个try / catch一个PersistenceException。问题是事务回滚然后它到达PersistenceException。

我知道Spring @Transactional默认在任何未经检查的异常中回滚,但我明确地告诉noRollbackFor PersistenceException。

为什么不能正常工作?有什么方法可以威胁吗?

感谢。

编辑 - 应用中的try / catch方法执行此操作:

try {
   insert();
}
catch(PersistenceException e)
{
   update();
}

Edit2 - log:

Transaction Manager Log

Edit3 - 异常处理部分:

if (acao.equalsIgnoreCase("I")) {
    try {
        insertQuery.executeUpdate();
    }
    catch(PersistenceException e) {
        int affected = updateQuery.executeUpdate();

        if(affected == 0)
            throw new LogApplyException("O insert falhou e o update não afetou registros.");
    }
}

Edit4 - 更多信息:

1)从apply中删除@Transactional,在此例外的applyLog结果上留下@Transaction:

javax.persistence.PersistenceException:org.hibernate.exception.GenericJDBCException:无法执行语句

2)与1相同,但在此异常上添加noRollbackFor = PersistenceException.class(在applyLog上)会产生结果:

org.springframework.transaction.TransactionSystemException:无法提交JPA事务;嵌套异常是javax.persistence.RollbackException:事务标记为rollbackOnly

编辑5:

@lzagkaretos解决方案有效(谢谢),但我想知道如何处理这种情况以备将来使用。

1 个答案:

答案 0 :(得分:0)

更新

我认为依赖于主键冲突异常以查找是否应插入或更新记录不是您应该做的事情。您可以使用的另一个实现是在执行之前查找记录是否已保存在数据库中以执行更新,或者不执行插入。

例如,如果您可以使用spring数据存储库,则代码可能如下所示。

public void apply(LogCompactoEntity entity) {

    LogCompactoEntity logCompactoEntity = (entity.getId() == null) ? new LogCompactoEntity() : logCompactoRepository.findOne(entity.getId());
    if (logCompactoEntity == null) {
        logCompactoEntity = new LogCompactoEntity();
    }

    copyProperties(entity, logCompactoEntity);

    logCompactoRepository.save(logCompactoEntity);
}

-

也许你不应该在apply方法中使用try / catch块并在方法签名中用throws PersistenceException声明它。

为了使noRollbackFor起作用,必须从apply方法抛出PersistenceException。您可以尝试以下方法。

try {
    insert();
}
catch(PersistenceException e) {
    update();
    throw e;
}