当前位置: 首页 > 知识库问答 >
问题:

合并实体,更改其id,再次合并,导致“映射到数据库中的主键列。不允许更新”错误

严锐
2023-03-14

我有一个JPA程序,其中Eclipse Link是持久性提供程序。当我合并一个用户实体、更改其ID并尝试再次合并同一个用户实例时,会抛出一个错误。我重写代码,以最简单的方式说明我的问题。

User user = userManager.find(1);
userManager.merge(user);
System.out.println("User is managed? "+userManager.contains(user);
user.setId(2);
userManager.merge(user);

上述代码不在事务上下文中。userManager是一个注入EntityManager的无状态会话bean。执行时,控制台将打印:

User is managed? false

Exception [EclipseLink-7251] (Eclipse Persistence Services - 2.1.3.v20110304-r9073): org.eclipse.persistence.exceptions.ValidationException
Exception Description: The attribute [id] of class [demo.model.User] is mapped to a primary key column in the database. Updates are not allowed.

异常发生在第二次合并()调用时。

如果我创建一个新用户,设置它的ID并合并它,它的工作原理:

User user = userManager.find(1);
userManager.merge(user);
System.out.println("User is managed? "+userManager.contains(user);
User newUser = new User();
newUser.setId(2);
userManager.merge(newUser);

那么,第一个场景和第二个场景之间的区别是什么?根据JPA规范,只要实体处于分离状态,合并就应该成功,对吗?(假设ID=2的实体存在)

为什么EclipseLink提供者似乎对用户实体之前已经合并的事实感到烦恼?

更新:这似乎是EclipseLink的一个bug。我已将持久性提供程序从EclipseLink替换为Hibernate:

我改变

<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>

<provider>org.hibernate.ejb.HibernatePersistence</provider>    

没有抛出任何错误。

共有3个答案

卫子平
2023-03-14

尝试

南宫奇思
2023-03-14

这似乎是日食的一种虫子。我已将持久性提供程序从EclipseLink更改为Hibernate:

<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>

<provider>org.hibernate.ejb.HibernatePersistence</provider>  

没有抛出错误。

EclipseLink的版本是2.3。2.(随最新的Glassfish应用程序服务器3.1.2一起提供)。

hibernate的最新版本是4.1。7.

苏彦君
2023-03-14

原因是,可以插入/定义Id,就像您在第二个示例中所做的那样,但不会像您在第一个示例中尝试的那样进行更改/更新。JPA提供程序试图反映数据库中的更改,但失败了。

JPA 2规范§2.4规定

应用程序不得更改主键的值。如果发生这种情况,行为是未定义的。

 类似资料:
  • 问题内容: 有没有一种方法可以将两个主键合并为一个,然后级联更新所有受影响的关系?这是场景: 客户(idCustomer int PK,公司varchar(50)等) CustomerContacts(idCustomerContact int PK,idCustomer int FK,名称varchar(50)等) CustomerNotes(idCustomerNote int PK,idCu

  • 我有遗产数据库。 表内容有一个PK列。siteId列不是PK的一部分。表程序有两个PK列(siteId、code)。它是复合PK。此表用作模板。程序中唯一的变量是parameter,它位于表内容的prog_param列上。 作为代码 但这不是工作。Hibernate引发“实体映射中重复列”异常。 所以我研究了一些解决方案。最后,我发现这个'Republic column in mapping fo

  • 我有一个非常简单的基于控制台的(不是应用服务器部署的)JPA程序,我对Eclipse Link和Hibernate提供商进行了测试。所有的代码都是JPA,所以我想我可以毫无问题地切换提供商。然而,当使用Hibernate作为提供程序时,程序会成功,但在Eclipse Link中会失败。 关键部分是这个(我在防火墙后面,所以我看不到格式,因为“所以需要来自另一个域的JavaScript…”因此,如果

  • 我已经尝试使用Spring Boot+Spring Data JPA更新实体很久了。我得到所有正确的观点回到我。我的编辑视图按ID向我返回正确的实体。一切进展顺利。直到我实际尝试保存/合并/持久化对象。每次我拿回一个有新ID的新实体。我只是不知道为什么。我看了网上的例子,还有你可能会参考的重复问题的链接。那么,在这些代码中,我在哪里犯了错误呢? 在这段代码之后。我的视图将我返回到正确的URL,但I

  • 我正在开发一个web应用程序,使用React跟踪水果供应商的库存。js,MongoDB,Node。js和Express。我调用了数据库endpoint来呈现表中的数据。现在,我尝试使用按钮增加和减少库存量,但当我尝试设置新状态时,它不起作用。我尝试通过单击更改状态,然后更新数据库中的新状态。有什么建议吗? > 可结果成分: 从'react'导入Reac,{Component};从“react bo

  • 问题内容: 我在SQL Server中运行合并。在我的更新中,我只想更新值已更改的行。版本行在每次更新时都会递增。下面是一个示例: 现在,如果我只想更新行,从而增加版本,则仅在名称更改的情况下。 问题答案: 可以有。另外,无需更新。 如果Last_Name或First_Name可为空,则例如在比较trg.Last_Name <> src.Last_Name时,需要注意值。