【问题标题】:EntityManager operations orderEntityManager 操作顺序
【发布时间】:2013-11-29 10:52:02
【问题描述】:

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

我所做的是删除实体调用

entityManager.remove();

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

entityManager.persist();

这两个操作在单个事务中执行,并按上述顺序执行。先去除,再添加。然而,由于违反了唯一约束,这些操作似乎以相反的顺序执行。看起来新实体是在删除前一个实体之前添加的。

显然,我可以打电话

entityManager.flush()

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

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

有什么方法可以在删除后不刷新或提交事务的情况下解决问题?

谢谢。

【问题讨论】:

    标签: java hibernate jpa transactions ejb


    【解决方案1】:

    显然,我可以拨打entityManager.flush()

    实际上你必须调用它。

    但是在这种情况下,数据会在 整个事务提交。

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

    我认为操作顺序与添加到的顺序相同 交易。从我的例子来看,事实并非如此。

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

    有什么方法可以在不刷新或提交 删除后的交易?

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

    【讨论】:

    • 我使用 JTA 并使用事务数据库 (Oracle),所以一切都应该没问题。精彩的解释安德烈。我在有关事务提交的问题上错了。现在很清楚了。我认为问题和答案也对其他人有用。谢谢。
    【解决方案2】:

    不推荐使用 Ossama Nasser 建议的解决方案,因为如果使用不同的事务,如果某些东西在第二个或下一个事务上失败,则回滚到初始状态的可能性无效。

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

    【讨论】:

    • 这不应添加为新答案,而应作为对您所指答案的评论。
    【解决方案3】:

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

    【讨论】:

    • 但是,我需要在一个事务中执行这两个操作。
    猜你喜欢
    • 2016-02-15
    • 2016-12-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多