Java 合并失败,复合标识符包含关联
我们正在使用hibernate来管理midPoint的存储库,midPoint是一个开源的身份管理系统。大约有70个实体 最近,我们遇到了一个问题,即合并具有包含关联的复合标识符的实体 这个问题可以用一个非常简单的例子来说明。它几乎直接来自于(除了关联的Java 合并失败,复合标识符包含关联,java,hibernate,Java,Hibernate,我们正在使用hibernate来管理midPoint的存储库,midPoint是一个开源的身份管理系统。大约有70个实体 最近,我们遇到了一个问题,即合并具有包含关联的复合标识符的实体 这个问题可以用一个非常简单的例子来说明。它几乎直接来自于(除了关联的OneToMany端) 让我们有一个父实体和一个子实体: Parent.java @实体 公共类父级实现可序列化{ @身份证 私有整数id; @OneToMany(fetch=FetchType.LAZY,mappedBy=“parent”, 孤
OneToMany
端)
让我们有一个父实体和一个子实体:
Parent.java
@实体
公共类父级实现可序列化{
@身份证
私有整数id;
@OneToMany(fetch=FetchType.LAZY,mappedBy=“parent”,
孤立删除=真,级联=级联类型.ALL)
private Set children=new HashSet();
//为了简洁起见,省略了getter、setter、equals和hashCode
}
Child.java
@实体
公共类子级实现可序列化{
@身份证
@manytone(fetch=FetchType.LAZY,可选=false)
私人家长;
@身份证
私有字符串值;
//为了简洁起见,省略了getter、setter、equals和hashCode
}
情况是:
publicstaticvoidmain(字符串[]args){
创建();
更新();
}
私有静态void create(){
Session Session=HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();
父项=新父项();
父。setId(10);
子项=新子项();
setParent(家长);
parent.getChildren().add(child);
child.setValue(“旧”);
session.save(父级);
session.getTransaction().commit();
session.close();
}
私有静态无效更新(){
Session Session=HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();
父项=新父项();
父。setId(10);
子项=新子项();
setParent(家长);
parent.getChildren().add(child);
child.setValue(“新”);
会话。合并(父级);
session.getTransaction().commit();
session.close();
}
它失败了,因为Hibernate试图将空值插入子表
Exception in thread "main" javax.persistence.PersistenceException: org.hibernate.exception.ConstraintViolationException: could not execute statement
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:149)
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:157)
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:164)
at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1443)
at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:493)
at org.hibernate.internal.SessionImpl.flushBeforeTransactionCompletion(SessionImpl.java:3207)
at org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:2413)
at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(JdbcCoordinatorImpl.java:473)
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.beforeCompletionCallback(JdbcResourceLocalTransactionCoordinatorImpl.java:156)
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.access$100(JdbcResourceLocalTransactionCoordinatorImpl.java:38)
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.commit(JdbcResourceLocalTransactionCoordinatorImpl.java:231)
at org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:68)
at simple.TestMergeParentChild.update(TestMergeParentChild.java:49)
at simple.TestMergeParentChild.main(TestMergeParentChild.java:10)
Caused by: org.hibernate.exception.ConstraintViolationException: could not execute statement
at org.hibernate.exception.internal.SQLStateConversionDelegate.convert(SQLStateConversionDelegate.java:112)
at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:42)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:111)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:97)
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:178)
at org.hibernate.engine.jdbc.batch.internal.NonBatchingBatch.addToBatch(NonBatchingBatch.java:45)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3013)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3513)
at org.hibernate.action.internal.EntityInsertAction.execute(EntityInsertAction.java:89)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:589)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:463)
at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:337)
at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:39)
at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1437)
... 10 more
Caused by: org.h2.jdbc.JdbcSQLException: NULL not allowed for column "VALUE"; SQL statement:
/* insert simple.Child */ insert into Child (value, parent_id) values (?, ?) [23502-193]
at org.h2.message.DbException.getJdbcSQLException(DbException.java:345)
at org.h2.message.DbException.get(DbException.java:179)
at org.h2.message.DbException.get(DbException.java:155)
at org.h2.table.Column.validateConvertUpdateSequence(Column.java:311)
at org.h2.table.Table.validateConvertUpdateSequence(Table.java:784)
at org.h2.command.dml.Insert.insertRows(Insert.java:151)
at org.h2.command.dml.Insert.update(Insert.java:114)
at org.h2.command.CommandContainer.update(CommandContainer.java:98)
at org.h2.command.Command.executeUpdate(Command.java:258)
at org.h2.jdbc.JdbcPreparedStatement.executeUpdateInternal(JdbcPreparedStatement.java:160)
at org.h2.jdbc.JdbcPreparedStatement.executeUpdate(JdbcPreparedStatement.java:146)
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:175)
... 19 more
查看源代码时,问题似乎在这里:
i、 e.在wherecopyValues
上,方法不会将任何内容从临时子实体复制到新创建的实例中(可能是因为它忽略了标识符)
对我来说,它就像冬眠中的一只虫子。但我没有足够的经验来确定。我试图解决的问题是:
@IdClass
和/或@EmbeddedId
。虽然这解决了的问题,但没有帮助,更直接地与我们的中点使用有关无法在org.hibernate.mapping.Table(AssignmentExtension)及其相关的超级表和辅助表中找到逻辑名称为:owner\u owner\u oid的列,这是我得到的异常。当我试图使用额外的@列(…,insertable=false,updateable=false)来解决它时,
除了代码变得越来越不理解之外,我还遇到了另一个问题
DefaultMergeEventListener
中的代码。我曾经用过一种方法。它有帮助(即使在我们的应用程序中),但我担心解决方案的丑陋性;除了其他事情,它使Hibernate考虑暂时的子实例被分离,因为现在它们确实有一个标识符(由应用程序提供)。
请问,我该如何处理这种情况?这是一个hibernate bug,将来可以修复吗?我是否应该探索@IdClass
方法,尝试解决出现的问题?我知道最自然的方法可能是在子表中引入人工(生成)ID,但我希望避免这种情况,因为有必要更改DB模式
多谢各位
编辑(2018-02-06):在我提交文件之后。基于
@EmbeddedId
的替代解决方案尚待验证。由于错误仍然存在,是否有人使用@EmbeddedId验证了该解决方案?