Hibernate"提供错误类型的id期望Long,得到类DelayedPostInsertIdentifier"例外

时间:2014-11-14 16:08:57

标签: java hibernate one-to-many hibernate-onetomany

简而言之:

当我尝试将新(未保存)实体添加到已保存父对象的一对多集时,在父实体上调用Merge之后,我得到以下异常:

  

为com.test.Child类提供了错误类型的id。预期:   class java.lang.Long,得到了类   org.hibernate.action.internal.DelayedPostInsertIdentifier

我找到了代表相同问题的故障单:https://hibernate.atlassian.net/browse/HHH-2382 它被拒绝了,对我的问题没什么帮助。

有人遇到过这个问题吗? 任何人都可以指出问题的根源和可能的解决方案吗?

详细问题:

我有两节课:     public class Parent extends BaseModel实现Serializable {         私人长身份;         私人套装儿童;     }

public class Child extends BaseModel implements Serializable {
    private long id;
    private String value;
}

我正在尝试执行以下代码:

Parent parent = new Parent();
parent.setChildren(new HashSet<Child>());

Child child = new Child();
child.setValue("First");
parent.getChildren().add(child);

parent = daoFacade.save(parent);

child = new Child();
child.setValue("Second");
parent.getChildren().add(child);

parent = daoFacade.save(parent);

第二次调用save方法后,我得到以下异常:

  

org.hibernate.TypeMismatchException:提供了错误类型的id   class com.text.Child。预计:类java.lang.Long,得到了类   org.hibernate.action.internal.DelayedPostInsertIdentifier at   org.hibernate.event.internal.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:134)     在org.hibernate.internal.SessionImpl.fireLoad(SessionImpl.java:1092)     在   org.hibernate.internal.SessionImpl.internalLoad(SessionImpl.java:1019)     在   org.hibernate.type.EntityType.resolveIdentifier(EntityType.java:648)     在org.hibernate.type.EntityType.resolve(EntityType.java:468)at   org.hibernate.type.EntityType.replace(EntityType.java:325)at   org.hibernate.type.CollectionType.replaceElements(CollectionType.java:517)     在org.hibernate.type.CollectionType.replace(CollectionType.java:667)     在org.hibernate.type.TypeHelper.replace(TypeHelper.java:177)at   org.hibernate.event.internal.DefaultMergeEventListener.copyValues(DefaultMergeEventListener.java:372)     在   org.hibernate.event.internal.DefaultMergeEventListener.entityIsPersistent(DefaultMergeEventListener.java:184)     在   org.hibernate.event.internal.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:157)     在   org.hibernate.event.internal.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:76)     在org.hibernate.internal.SessionImpl.fireMerge(SessionImpl.java:914)     在org.hibernate.internal.SessionImpl.merge(SessionImpl.java:898)at   org.hibernate.internal.SessionImpl.merge(SessionImpl.java:902)at   com.test.DAOFacade.saveObject(DAOFacade.java:273)at   com.test.Test.testSaving(MemcachedTest.java:99)

DaoFacade.save方法看起来如下:

public void saveOrUpdate(T obj) {
    Session session = getSession();

    BaseModel model = (BaseModel) obj;
    if (model.isNew()) {
        T merged = (T)session.merge(obj);
        session.update(merged);
    } else {
        session.saveOrUpdate(obj);
    }
    session.flush();
}

Hibernate映射是:

<class name="Parent" table="PARENT">
    <id name="id" column="id" unsaved-value="0">
        <generator class="native"/>
    </id>
    <set name="children" inverse="false" lazy="false" cascade="all">
        <cache usage="read-write" />
        <key column="LINK_ID"/>
        <one-to-many class="Child"/>
    </set>       
</class>

<class name="Child" table="CHILD">
    <cache usage="read-write" />

    <id name="id" column="id" unsaved-value="0">
            <generator class="native"/>
        </id>

        <property name="value" type="string" column="VALUE" not-null="true" lazy="false"/>       
</class>

我已经进行了几个小时的调试,并且所有进程在Hibernate中似乎都是正确的,但事实上它会导致以下问题:

  • 在合并期间,在迭代字段期间,未保存的“第二个”子项为 找到。
  • “Second”Child标记为insert,插入查询已准备好并被放入QueryQueue。
  • 继续合并过程,Hibernate在某个时刻试图加载“第二个”孩子
  • 但它尚未插入并且提出了Excpetion。

2 个答案:

答案 0 :(得分:2)

我也遇到过这个问题。请注意,saveOrUpdate方法未启动事务。解决方法是启动事务并确保在调用session.update或session.saveOrUpdate之后提交事务。

更新saveOrUpdate方法,如下所示:

public void saveOrUpdate(T obj) {
   Session session = getSession();
   Transaction tx = null;
   try {
      tx = session.beginTransaction();
      BaseModel model = (BaseModel) obj;
      if (model.isNew()) {
        T merged = (T)session.merge(obj);
        session.update(merged);
      } else {
        session.saveOrUpdate(obj);
      }
      tx.commit();
   } catch (Exception ex) {
      tx.rollback();
   }

}

这个thread给了我一个问题解决方案的提示,saveOrUpdate方法验证了丢失的事务。

答案 1 :(得分:0)

使用Hibernate 4.2.15和Spring时遇到了同样的问题。正如@arjaynacion所建议的那样,在执行保存的方法中添加@Transactional注释解决了问题:

@Transactional
 @NotNull
 protected S save(@NotNull S entity)
 {
    return getDao().save(entity);
 }