Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/373.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 合并失败,复合标识符包含关联_Java_Hibernate - Fatal编程技术网

Java 合并失败,复合标识符包含关联

Java 合并失败,复合标识符包含关联,java,hibernate,Java,Hibernate,我们正在使用hibernate来管理midPoint的存储库,midPoint是一个开源的身份管理系统。大约有70个实体 最近,我们遇到了一个问题,即合并具有包含关联的复合标识符的实体 这个问题可以用一个非常简单的例子来说明。它几乎直接来自于(除了关联的OneToMany端) 让我们有一个父实体和一个子实体: Parent.java @实体 公共类父级实现可序列化{ @身份证 私有整数id; @OneToMany(fetch=FetchType.LAZY,mappedBy=“parent”, 孤

我们正在使用hibernate来管理midPoint的存储库,midPoint是一个开源的身份管理系统。大约有70个实体

最近,我们遇到了一个问题,即合并具有包含关联的复合标识符的实体

这个问题可以用一个非常简单的例子来说明。它几乎直接来自于(除了关联的
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.在where
    copyValues
    上,方法不会将任何内容从临时子实体复制到新创建的实例中(可能是因为它忽略了标识符)

    对我来说,它就像冬眠中的一只虫子。但我没有足够的经验来确定。我试图解决的问题是:

  • 我将普通标识符替换为
    @IdClass
    和/或
    @EmbeddedId
    。虽然这解决了的问题,但没有帮助,更直接地与我们的中点使用有关
  • 更复杂场景的问题是,
    无法在org.hibernate.mapping.Table(AssignmentExtension)及其相关的超级表和辅助表中找到逻辑名称为:owner\u owner\u oid的列,这是我得到的异常。当我试图使用额外的
    @列(…,insertable=false,updateable=false)来解决它时,
    除了代码变得越来越不理解之外,我还遇到了另一个问题
  • 我试图通过使用告诉hibernate有关标识符的信息,但没有任何帮助
  • 作为最后一种手段,我试图通过说服瞬态实体实际上有一个标识符来解决
    DefaultMergeEventListener
    中的代码。我曾经用过一种方法。它有帮助(即使在我们的应用程序中),但我担心解决方案的丑陋性;除了其他事情,它使Hibernate考虑暂时的子实例被分离,因为现在它们确实有一个标识符(由应用程序提供)。 请问,我该如何处理这种情况?这是一个hibernate bug,将来可以修复吗?我是否应该探索
    @IdClass
    方法,尝试解决出现的问题?我知道最自然的方法可能是在子表中引入人工(生成)ID,但我希望避免这种情况,因为有必要更改DB模式

    多谢各位


    编辑(2018-02-06):在我提交文件之后。基于
    @EmbeddedId
    的替代解决方案尚待验证。

    由于错误仍然存在,是否有人使用@EmbeddedId验证了该解决方案?