我最近遇到了有趣的问题。我在JPA + Hibernate + EJB项目中使用。该问题涉及在同一事务中保存和删除实体。使用的数据库表在两列上定义了唯一的约束。
我所做的是删除实体调用
entityManager.remove();然后,使用以下方法将新实体的值添加到与在唯一约束中使用的列相关联的两个属性中,而在其他属性中添加不同的值:
entityManager.persist();这两个操作在单个事务中执行,并按上述顺序执行。先移除,再加。然而,由于违反了唯一约束,这些操作似乎是按倒排顺序执行的。看起来,在删除前一个实体之前添加了新实体。
很明显,我可以打电话
entityManager.flush()移除后,则不违反约束。但是,在这种情况下,在整个事务提交之前将数据保存到数据库中。这不是一种可取的行为。如果在刷新后出了任何问题,并且事务将被标记为回滚,那么该实体将被删除。
我认为操作顺序与添加到事务中的操作顺序相同。从我的例子来看,事实证明并非如此。
删除后是否有任何解决问题的方法而不刷新或提交事务?
谢谢。
发布于 2013-11-29 11:07:37
显然,我可以打电话给
entityManager.flush()
实际上你必须叫它。
但是,在这种情况下,在整个事务提交之前将数据保存到数据库中。
这是错误的:数据是同步到DB的,但是事务仍然没有提交,除非您手动提交它并拥有对DB的控制。如果您没有在EJB中配置任何东西,并且您的持久性单元是JTA (请参阅this question with comments),那么只有在方法从EJB层返回之后才会提交事务。
我认为操作顺序与添加到事务中的操作顺序相同。从我的例子来看,事实证明并非如此。
不,JPA规范并不强制实现这样做。这就是为什么有一个flush()操作。
删除后是否有任何解决问题的方法而不刷新或提交事务?
是的,正如我说的,使用flush()。还要确保您使用的是事务性数据库引擎(例如,MyIsam中的MySql不支持事务)。
发布于 2014-12-12 11:43:18
Ossama Nasser建议的解决方案是不推荐的,因为使用不同的事务,如果第二次或下一次事务发生故障,那么回滚到初始状态的可能性就无效了。
entityManager.flush()是正确的解决方案。
发布于 2013-11-29 11:11:41
我也遇到了同样的问题,我就这样解决了:
EntityManager.getTransaction().begin();
EntityManager.remove();
EntityManager.persist();
EntityManager.getTransaction().commit();
如果出现任何问题,将移除和持久化操作分为两个不同的事务。
https://stackoverflow.com/questions/20284027
复制相似问题