EntityManager操作顺序

问题描述 投票:4回答:3

我最近遇到了一个有趣的问题。我在项目JPA + Hibernate + EJB中使用。该问题涉及在同一事务中保存和删除实体。使用的数据库表具有在两列上定义的唯一约束。

我所做的是删除实体调用

entityManager.remove();

然后,新实体在与唯一约束中使用的列关联的两个属性中添加相同的值,但使用其他属性中的不同值:

entityManager.persist();

这两个操作在单个事务中执行,并按照上述顺序执行。首先去除,再加上第二个。但是,当违反唯一约束时,操作似乎以反转顺序执行。看起来在删除前一个实体之前添加了新实体。

显然,我可以打电话

entityManager.flush()

删除后,然后不违反约束。但是,在这种情况下,数据在整个事务提交之前保存到数据库中。这不是一个理想的行为。如果在刷新之后出现任何问题并且事务将被标记为回滚,则无论如何都将删除该实体。

我认为操作顺序与添加到事务中的操作顺序相同。从我的例子可以看出事实并非如此。

删除后没有刷新或提交事务有没有办法解决问题?

谢谢。

java hibernate jpa transactions ejb
3个回答
5
投票

显然,我可以打电话给entityManager.flush()

实际上你必须打电话给它。

但是,在这种情况下,数据在整个事务提交之前保存到数据库中。

这是错误的:数据被同步到数据库,但事务仍未提交,除非您手动提交并控制数据库。如果您没有在EJB中配置任何内容,并且您的持久性单元是JTA(请参阅this question with comments),那么只有在方法从EJB层返回后才会提交事务。

我认为操作顺序与添加到事务中的操作顺序相同。从我的例子可以看出事实并非如此。

不,JPA规范不强制实现这样做。这就是为什么有一个flush()操作。

删除后没有刷新或提交事务有没有办法解决问题?

是的,正如我所说的使用flush()。还要确保使用事务数据库引擎(例如,MySql中的MyIsam不支持事务)。


2
投票

不建议使用Ossama Nasser建议的解决方案,因为如果某些东西在第二次或下一次交易中失败,使用不同的交易会使回滚到初始状态的可能性无效。

entityManager.flush()是正确的解决方案。


0
投票

我确实遇到了同样的问题,我解决了这个问题: EntityManager.getTransaction().begin(); EntityManager.remove(); EntityManager.persist(); EntityManager.getTransaction().commit(); 如果出现任何问题,请将删除和持久操作转换为两个不同的事务

© www.soinside.com 2019 - 2024. All rights reserved.