首页 文章

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

提问于
浏览
2

我有以下方法:

@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 - 日志:

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

    UPDATE

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

    例如,如果您可以使用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;
    }
    

相关问题