gpt4 book ai didi

mysql - EclipseLink: native 查询 INSERT INTO 上的 "Updates are not allowed"

转载 作者:行者123 更新时间:2023-11-30 22:53:07 24 4
gpt4 key购买 nike

自从从 EL 2.1 升级到 EclipseLink 2.5 后,我们在之前运行的代码上得到了 PersistenceException。场景非常简单:我们有两个相同的表,唯一的区别是一个是另一个的“历史”版本。基本上,当我们确定某行不会再更改时,我们将该行移至历史表。这意味着虽然 id 是在第一个表上生成的,但它在历史表上是“继承”的。以下是实体:

@Entity
@Table(name = "DOCUMENT")
public class Document implements Serializable {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private long id;
// Some other fields
}

@Entity
@Table(name = "DOCUMENT_HISTORY")
public class DocumentHistory implements Serializable {
@Id
private long id;
// Some other fields
}

为了将一行移动到历史表中,我们使用原生查询(因为某些列未映射为实体类中的字段):

String query = "INSERT INTO DOCUMENT_HISTORY SELECT * FROM DOCUMENT t WHERE t.id=?1";
Query updateQuery = entityManager.createNativeQuery(query);
updateQuery.setParameter(1, document.getId());
updateQuery.executeUpdate();

执行此查询时,有时会抛出此异常:

javax.persistence.PersistenceException: Exception [EclipseLink-7251] (Eclipse Persistence Services - 2.5.1.v20130918-f2b9fc5): 
org.eclipse.persistence.exceptions.ValidationException
Exception Description: The attribute [id] of class [org.myc.entities.jpa.company.DocumentHistory] is mapped to a primary key column in the database. Updates are not allowed.
at org.eclipse.persistence.internal.jpa.EntityManagerImpl.flush(EntityManagerImpl.java:868)
at org.eclipse.persistence.internal.jpa.QueryImpl.performPreQueryFlush(QueryImpl.java:963)
at org.eclipse.persistence.internal.jpa.QueryImpl.executeUpdate(QueryImpl.java:296)
at org.myc.utility.jpa.user.DocumentManager.toDocumentHistory(DocumentManager.java:141)
at java.lang.Thread.run(Thread.java:662)
Caused by: Exception [EclipseLink-7251] (Eclipse Persistence Services - 2.5.1.v20130918-f2b9fc5): org.eclipse.persistence.exceptions.ValidationException
Exception Description: The attribute [id] of class [org.myc.entities.jpa.company.DocumentHistory] is mapped to a primary key column in the database. Updates are not allowed.
at org.eclipse.persistence.exceptions.ValidationException.primaryKeyUpdateDisallowed(ValidationException.java:2548)
at org.eclipse.persistence.mappings.foundation.AbstractDirectMapping.writeFromObjectIntoRowWithChangeRecord(AbstractDirectMapping.java:1257)
at org.eclipse.persistence.internal.descriptors.ObjectBuilder.buildRowForUpdateWithChangeSet(ObjectBuilder.java:1768)
at org.eclipse.persistence.internal.queries.DatabaseQueryMechanism.updateObjectForWriteWithChangeSet(DatabaseQueryMechanism.java:1030)
at org.eclipse.persistence.queries.UpdateObjectQuery.executeCommitWithChangeSet(UpdateObjectQuery.java:84)
at org.eclipse.persistence.internal.queries.DatabaseQueryMechanism.executeWriteWithChangeSet(DatabaseQueryMechanism.java:301)
at org.eclipse.persistence.queries.WriteObjectQuery.executeDatabaseQuery(WriteObjectQuery.java:58)
at org.eclipse.persistence.queries.DatabaseQuery.execute(DatabaseQuery.java:899)
at org.eclipse.persistence.queries.DatabaseQuery.executeInUnitOfWork(DatabaseQuery.java:798)
at org.eclipse.persistence.queries.ObjectLevelModifyQuery.executeInUnitOfWorkObjectLevelModifyQuery(ObjectLevelModifyQuery.java:108)
at org.eclipse.persistence.queries.ObjectLevelModifyQuery.executeInUnitOfWork(ObjectLevelModifyQuery.java:85)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.internalExecuteQuery(UnitOfWorkImpl.java:2896)
at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1793)
at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1775)
at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1726)
at org.eclipse.persistence.internal.sessions.CommitManager.commitChangedObjectsForClassWithChangeSet(CommitManager.java:267)
at org.eclipse.persistence.internal.sessions.CommitManager.commitAllObjectsForClassWithChangeSet(CommitManager.java:192)
at org.eclipse.persistence.internal.sessions.CommitManager.commitAllObjectsWithChangeSet(CommitManager.java:138)
at org.eclipse.persistence.internal.sessions.AbstractSession.writeAllObjectsWithChangeSet(AbstractSession.java:4196)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitToDatabase(UnitOfWorkImpl.java:1441)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitToDatabaseWithPreBuiltChangeSet(UnitOfWorkImpl.java:1587)
at org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.writeChanges(RepeatableWriteUnitOfWork.java:452)
at org.eclipse.persistence.internal.jpa.EntityManagerImpl.flush(EntityManagerImpl.java:863)
... 5 more

有人遇到同样的问题吗?为什么您认为这不会发生在所有行上,而只会发生在其中一些行上(没有明显的特定特征)?提前致谢,吕克

P.S.:EL 对原生查询执行映射/查询验证是否正确?

最佳答案

如 JPA 2.0 规范所述,executeUpdate() 执行更新或删除语句,因此不支持插入。

您可以使用 EntityManager(在事务中)通过持久化和刷新将实体插入到基础数据库中。您的特定情况下的虚拟示例可能如下所示:

// transaction starts
Document doc = em.find(Document.class, id);
DocumentHistory docHistory = new DocumentHistory(doc);
em.persist(docHistory);
// transaction ends

注意:您可以考虑使用 EclipseLink's auditing 而不是专有解决方案(这很好)特点:

EclipseLink also support full history support, which allows a complete history of all changes made to the database to be tracked in a mirror history table.

关于mysql - EclipseLink: native 查询 INSERT INTO 上的 "Updates are not allowed",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27484162/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com