【问题标题】:JPA 2.0 Entity update with new relationship fails on persist but succeeds on merge具有新关系的 JPA 2.0 实体更新在持久时失败,但在合并时成功
【发布时间】:2013-02-05 22:09:10
【问题描述】:

我定义了以下关系

实体 A 与实体 B 具有 @OneToMany,实体 B 具有 @OneToOne 与实体 C。

在创建实体 A 时,我还创建了实体 B 并设置了它们之间的关系。一切都按预期工作。

在另一笔交易中, - 从数据库中获取实体 A,获取相应的实体 B,然后 - 创建实体 C。 - 实体 C 设置在实体 B 上,以伪造两者之间的关系。 如果我使用 EntityManager.persist(Entity B),持久性管理器会尝试将实体 B 再次插入数据库,从而导致对实体 B 的 PK 的唯一约束违反。 如果我使用 EntityManager.merge(Entity B),一切都按预期工作。

在上述使用环境中,为什么要持久化操作尝试创建副本,因为在这种情况下管理实体并且它应该可以轻松进行更新。

【问题讨论】:

    标签: jpa-2.0 eclipselink


    【解决方案1】:

    如果对非托管实例调用 persist,JPA 要求提供者抛出异常。只能使用合并,因为很明显它从实例中获取数据并将其合并到托管副本中。如果 B 是托管的,persist 调用将被忽略,因此这意味着 B 是如何分离的,或者它是在与您调用 persist 不同的 entityManager 中读取的。

    【讨论】:

    • 是的,B 正在被另一个 entityManager 实例读取。如果应用程序仅部署在 Web 容器(而不是 EE)中,则服务定位器模式可能对管理持久性资源很有用。我知道实体管理器工厂是线程安全的。 Entity Manager 实例本身呢?使用服务定位器模式为整个应用程序提供共享的实体管理器实例是否有意义?
    • EntityManager 不是线程安全的,旨在表示事务上下文。如果您在事务中创建实体 C,则应从同一个 EM 中获取 B,以便托管实例与 C 相关联。为整个应用程序共享单个 EM 并不好,但有意义的是为逻辑工作单元共享,然后关闭或清除。
    猜你喜欢
    • 1970-01-01
    • 2014-09-02
    • 1970-01-01
    • 1970-01-01
    • 2012-12-17
    • 1970-01-01
    • 1970-01-01
    • 2013-01-30
    • 2018-04-09
    相关资源
    最近更新 更多