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

Hibernate正常,但ElipseLink失败:类[Y]的属性[x]映射到数据库中的主键列不允许更新

督嘉言
2023-03-14

我有一个非常简单的基于控制台的(不是应用服务器部署的)JPA程序,我对Eclipse Link和Hibernate提供商进行了测试。所有的代码都是JPA,所以我想我可以毫无问题地切换提供商。然而,当使用Hibernate作为提供程序时,程序会成功,但在Eclipse Link中会失败。

关键部分是这个(我在防火墙后面,所以我看不到格式,因为“所以需要来自另一个域的JavaScript…”因此,如果格式不正确,我深表歉意-我将在家中进行格式设置):

em.getTransaction().begin();
Employee emp = service.createEmployee(id, "John Doe", 45000,1);
em.getTransaction().commit();                                        
System.out.println("Persisted "+emp);
em.getTransaction().begin();
em.getTransaction().commit();

我曾经在第二个空事务中做过一些事情,但在缩小问题范围时,我注意到即使我不做任何事情就立即开始()和提交(),它也会失败。有趣的是EclipseLink(见文章底部的stack trace)似乎抱怨entity Speciality的id属性正在更新,尽管它没有更新。

员工实体具有专业实体的外键(每个员工都有一个专业),即员工的多对一关系:

 @Entity
 public class Employee {
 @Id                                                            
 @Basic(optional = false)                                       
 @NotNull                                                       
 private int id;                                                
 private String name;                                           
 private long salary;                                           
 @JoinColumn(name = "spc_id", referencedColumnName = "id")      
 @ManyToOne(optional = false)                                   
 private Specialty spcId;
 ...}

专业类定义为:

@Entity                                                  
public class Specialty {                                 
@Id                                                  
@Basic(optional = false)                             
@NotNull                                             
private int id;
... }

当使用Hibernate作为JPA提供程序时,代码执行平稳。当使用EclipseLink时,它会失败,因为在本文底部找到了堆栈跟踪。

更新:经过进一步的实验,我发现以下代码适用于两个提供商:

em.getTransaction().begin();                                      
Employee emp = service.createEmployee(id, "John Doe", 45000, 1);  
em.getTransaction().commit();                                     
System.out.println("Persisted " + emp);                           
EntityManager em2 = emf.createEntityManager();
em2.getTransaction().begin();                                     
em2.getTransaction().commit();                                    
em2.close();          

这仍然不能解释为什么EclipseLink在尝试在同一个实体管理器对象上开始()/commit()事务时失败(em-请参阅本文开头的代码),而且还不能解释为什么它会因为这样一条神秘的消息而失败(抱怨类Speciality的主键正在更新)。

堆栈跟踪:

[java] [EL Info]: 2012-07-12 11:21:09.453--ServerSession(23846608)--EclipseLink, version: Eclipse Persistence Services - 2.4.0.v20120608-r11652
 [java] [EL Info]: connection: 2012-07-12 11:21:09.59--ServerSession(23846608)--file:/home/mperdikeas/playground/jpa/01-employee-job/prj/use/build/employeetest.jar_EmployeeService login successful
 [java] Exception in thread "main" javax.persistence.RollbackException: Exception [EclipseLink-7251] (Eclipse Persistence Services - 2.4.0.v20120608-r11652): org.eclipse.persistence.exceptions.ValidationException
 [java] Exception Description: The attribute [id] of class [mp.Specialty] is mapped to a primary key column in the database. Updates are not allowed.
 [java]     at org.eclipse.persistence.internal.Persisted mp.Employee@ea70f2
 [java] [EL Warning]: 2012-07-12 11:21:09.735--UnitOfWork(32118258)--Exception [EclipseLink-7251] (Eclipse Persistence Services - 2.4.0.v20120608-r11652): org.eclipse.persistence.exceptions.ValidationException
 [java] Exception Description: The attribute [id] of class [mp.Specialty] is mapped to a primary key column in the database. Updates are not allowed.
 [java] [EL Info]: connection: 2012-07-12 11:21:09.738--ServerSession(23846608)--file:/home/mperdikeas/playground/jpa/01-employee-job/prj/use/buildjpa.transaction.EntityTransactionImpl.commitInternal(EntityTransactionImpl.java:102)
 [java]     at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionImpl.commit(EntityTransactionImpl.java:63)
 [java]     at mp.EmployeeTest.main(EmployeeTest.java:29)
 [java] Caused by: Exception [EclipseLink-7251] (Eclipse Persistence Services - 2.4.0.v20120608-r11652): org.eclipse.persistence.exceptions.ValidationException
 [java] Exception Description: The attribute [id] of class [mp.Specialty] is mapped to a primary key column in the database. Updates are not allowed.
 [java]     at org.eclipse.persistence.exceptions.ValidationException.primaryKeyUpdateDisallowed(ValidationException.java:2458)
 [java]     at org.eclipse.persistence.mappings.foundation.AbstractDirectMapping.writeFromObjectIntoRowWithChangeRecord(AbstractDirectMapping.java:1214)
 [java]     at org.eclipse.persistence.internal.descriptors.ObjectBuilder.buildRowForUpdateWithChangeSet(ObjectBuilder.java:1378)
 [java]     at org.eclipse.persistence.internal.queries.DatabaseQueryMechanism.updateObjectForWriteWithChangeSet(DatabaseQueryMechanism.java:1003)
 [java]     at org.eclipse.persistence.queries.UpdateObjectQuery.executeCommitWithChangeSet(UpdateObjectQuery.java:84)
 [java]     at org.eclipse.persistence.internal.queries.DatabaseQueryMechanism.executeWriteWithChangeSet(DatabaseQueryMechanism.java:286)
 [java]     at org.eclipse.persistence.queries.WriteObjectQuery.executeDatabaseQuery(WriteObjectQuery.java:58)
 [java]     at org.eclipse.persistence.queries.DatabaseQuery.execute(DatabaseQuery.java:852)
 [java]     at org.eclipse.persistence.queries.DatabaseQuery.executeInUnitOfWork(DatabaseQuery.java:751)
 [java]     at org.eclipse.persistence.queries.ObjectLevelModifyQuery.executeInUnitOfWorkObjectLevelModifyQuery(ObjectLevelModifyQuery.java:108)
 [java]     at org.eclipse.persistence.queries.ObjectLevelModifyQuery.executeInUnitOfWork(ObjectLevelModifyQuery.java:85)
 [java]     at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.internalExecuteQuery(UnitOfWorkImpl.java:2875)
 [java]     at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1602)
 [java]     at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1584)
 [java]     at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1535)
 [java]     at org.eclipse.persistence.internal.sessions.CommitManager.commitChangedObjectsForClassWithChangeSet(CommitManager.java:265)
 [java]     at org.eclipse.persistence.internal.sessions.CommitManager.commitAllObjectsWithChangeSet(CommitManager.java:128)
 [java]     at org.eclipse.persistence.internal.sessions.AbstractSession.writeAllObjectsWithChangeSet(AbstractSession.java:3914)
 [java]     at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitToDatabase(UnitOfWorkImpl.java:1419)
 [java]     at org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.commitToDatabase(RepeatableWriteUnitOfWork.java:634)
 [java]     at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitToDatabaseWithChangeSet(UnitOfWorkImpl.java:1509)
 [java]     at org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.commitRootUnitOfWork(RepeatableWriteUnitOfWork.java:266)
 [java]     at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitAndResume(UnitOfWorkImpl.java:1147)
 [java]     at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionImpl.commitInternal(EntityTransactionImpl.java:84)
 [java]     ... 2 more
 [java] /employeetest.jar_EmployeeService logout successful

共有3个答案

罗诚
2023-03-14

尝试

云昊阳
2023-03-14

它可能是:

@Entity                                                  
public class Specialty {                                 
@Id                                                  
@Basic(optional = false)                             
@NotNull
@GeneratedValue(strategy = GenerationType.AUTO)                                         
private int id;
... }
云瑞
2023-03-14

Eclipse Link不允许您更新PK(如果这个PK没有任何FK,一些DBMS允许这样做)

周围有2个工作:

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

  • 我有一个JPA程序,其中Eclipse Link是持久性提供程序。当我合并一个用户实体、更改其ID并尝试再次合并同一个用户实例时,会抛出一个错误。我重写代码,以最简单的方式说明我的问题。 上述代码不在事务上下文中。userManager是一个注入EntityManager的无状态会话bean。执行时,控制台将打印: 异常发生在第二次合并()调用时。 如果我创建一个新用户,设置它的ID并合并它,它的

  • 是否可以使用Hiberanate映射数据库列,这样我就可以在HQL查询中使用它,但不能将它映射到映射类中的实际属性? 由于数据库强加给我们的表名和列名类似于hashcodes,我们希望使用HQL进行更新,它可以使用漂亮的映射名称。因此,我们需要在Hibernate中映射列。

  • 1. 前言 本节课和大家一起聊聊 Hibernate 中的主键策略。通过本节课程,你将了解到: 什么是主键策略及主键生成器的种类; 如何映射复合主键。 2. 主键策略 Hibernate 进行数据库操作时,可依靠主键生成器组件更快速、准确地进行一系列操作。这便是主键策略。 2.1 主键生成器 主键是关系数据库中的概念,目的是唯一标识表中记录,保证实体数据的完整性。 关系数据库中表与表中数据的关系描

  • 我正在使用hibernate从数据库中获取数据。我们有20个节点的oracle RAC数据库。 现在的问题是,如果数据库的一个节点失败,我必须在运行时切换到另一个节点,而应用程序不会抛出错误,如果该节点关闭,我必须像wise一样切换到第三个节点。 当我们使用传统的JDBC风格建立连接时,可以很容易地完成,因为当与节点的连接失败时,连接对象将为null 这就是我创建会话工厂的方式, 私有静态最终Se

  • 在MySQL数据库上有一个没有任何主键的表。我想使用hibernate访问Java的数据端。但是,hibernate无法解析映射文档。其他表映射正确。这个问题是不是没有主键的原因?我必须至少创建一个主键来映射此表吗?还是还有别的什么? 表