【问题标题】:JPA EntityManager Merge ExceptionJPA EntityManager 合并异常
【发布时间】:2023-03-23 15:25:02
【问题描述】:

当存在具有相同主键的现有实体时,我尝试将实体合并到数据库中时收到primaryKeyUpdateDisallowed ValidationException

当然,当我执行TypedQuery 并让实体管理器首先返回实体,更新适当的值,然后合并时,我没有遇到异常。问题是这个过程在资源方面太昂贵了。我需要能够简单地合并而不会产生异常。

有没有办法构造我们的实体类,以便我们可以覆盖记录,包括主键?还是用其他方法解决问题?

【问题讨论】:

  • 向我们展示您的代码。此异常表明您正在尝试更改持久实体的 PK 值,这是禁止的。

标签: jpa merge entitymanager


【解决方案1】:

在 JPA 中,如果您愿意:

entityManager.merge(someEntity);

那么您必须首先将 someEntity 从数据库加载到 entityManager 持久性上下文中,然后通过“entityManager.detach(someEntity)”或通过清除持久性上下文进行分离。如果 someEntity 没有预先加载和分离,而是通过“new SomeEntity()”创建,则 merge() 函数将确定您添加了新实体并执行非常类似于 entityManager.persist(某个实体)。当数据在事务中被flush或commit时,会产生一个SQL INSERT,这会和已经存在的PK冲突。

这是来自 JPA 2 规范的指定行为:


应用于实体 X 的合并操作的语义如下:

  • 如果 X 是分离实体,则 X 的状态被复制到具有相同身份的预先存在的托管实体实例 X' 上,或者创建 X 的新托管副本 X'。
  • 如果 X 是一个新的实体实例,则创建一个新的托管实体实例 X',并将 X 的状态复制到新的托管实体实例 X'。

> 问题是这个过程在资源方面太昂贵了。我需要能够简单地合并而不会产生异常。

这不应该是这样的。从数据库中检索实体或实体列表应该是有效的。可能您的查询可以改进。查询中有“where”子句吗?刷新期间是否有很多实体级联(通过 @OneToMany 或 @ManyToOne 等关系上的属性 cascade=CascadeType.REFRESH/ALL)?您是否有一个包含许多实体/表的非常复杂的继承层次结构?如果您可以提供您的 JPQL 或条件查询,我相信问题将很容易解决。 :-)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-05-25
    • 1970-01-01
    • 2023-04-10
    • 1970-01-01
    • 1970-01-01
    • 2015-12-06
    • 1970-01-01
    • 2010-10-22
    相关资源
    最近更新 更多