在JPA事务中插入失败后对ConstraintViolationException的特殊处理

时间:2015-04-19 09:26:28

标签: jpa transactions

我想在单个事务中执行几个db操作。 它应该回滚所有失败,但是一个:在所有db-ops的middel中将有一个insert语句,它将生成的数字插入到具有唯一约束的字段中。 如果由于生成的数字已经存在而导致此插入失败,则应使用新生成的数字重复此插入,直到成功为止。但是这个插入不应该影响其他操作。

由于JPA中没有嵌套的tx,我不确定这里的最佳实践是什么。我想知道这是不是一个罕见的情况。

我尝试使用"嵌入式" tx,使用requires-new打开,挂起周围的tx并在成功插入随机数后重新开始。 部分工作:如果周围的tx中存在异常,则所有内容都会回滚,但随机数字插入。

如果我使用一个单独的tx,我不知道我应该如何确定为什么这个tx无法提交。所以我不知道我是否必须用一个新的随机数重复所有操作,或者因为另一个失败而离开它。

我还尝试在插入之后明确刷新实体管理器会话以强制执行异常,然后继续其余的工作,希望我可以通过编程方式从EM中删除该实体并再试一次。 但是在插入失败后我没有找到从EM中删除该实体的方法吗?

我也在使用Spring和SpringDataJPA。

@Transactional
public void doSomeThing() {

    SomeEntity fooEntity = new SomeEntity()
    someEntityRepository.save(fooEntity);

    someMoreDbOPs();

    RandomNoEntity rndEnt = new RandomNoEntity();
    while (true) {
            try {
                    rndEnt.setRandomNumber(generateRandomNumber());
                    entityManager.persist(rndEnt);
                    entityManager.flush();
                    break;
            } catch (ConstraintViolationException)
            {
                    //entityManager.detach(rndEnt); // didnt work
                    //entityManager.remove(rndEnt); // didnt work
            }
    }

    SomeEntity barEntity = new SomeEntity()
    someEntityRepository.save(barEntity);

    someMoreDbOPs();
}

我希望这个伪代码有助于描述我想要做的事情。

提前感谢任何帮助...

0 个答案:

没有答案