4

In short:

When I try to add New(Unsaved) Entities to one-to-many set of the saved parent, after calling Merge on the Parent entity, I get the following exception:

Provided id of the wrong type for class com.test.Child. Expected: class java.lang.Long, got class org.hibernate.action.internal.DelayedPostInsertIdentifier

I've found a ticket representing the same issue: https://hibernate.atlassian.net/browse/HHH-2382 It was rejected and doesn't help much with my question.

Did anybody face this problem? Can anybody point the source of the problem and the possible solution?

Problem in details:

I have two classes: public class Parent extends BaseModel implements Serializable { private long id; private Set children; }

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

I am trying to perform the following code:

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);

And after calling save method second time, I get the following Exception:

org.hibernate.TypeMismatchException: Provided id of the wrong type for class com.text.Child. Expected: class java.lang.Long, got class org.hibernate.action.internal.DelayedPostInsertIdentifier at org.hibernate.event.internal.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:134) at org.hibernate.internal.SessionImpl.fireLoad(SessionImpl.java:1092) at org.hibernate.internal.SessionImpl.internalLoad(SessionImpl.java:1019) at org.hibernate.type.EntityType.resolveIdentifier(EntityType.java:648) at 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) at org.hibernate.type.CollectionType.replace(CollectionType.java:667) at org.hibernate.type.TypeHelper.replace(TypeHelper.java:177) at org.hibernate.event.internal.DefaultMergeEventListener.copyValues(DefaultMergeEventListener.java:372) at org.hibernate.event.internal.DefaultMergeEventListener.entityIsPersistent(DefaultMergeEventListener.java:184) at org.hibernate.event.internal.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:157) at org.hibernate.event.internal.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:76) at org.hibernate.internal.SessionImpl.fireMerge(SessionImpl.java:914) at 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 method looks the following way:

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 mappings are:

<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>

I've been debugging for hours and all processes seem to go correclty in Hibernate, but in fact it leads to the following problem:

  • During merge, during iterating fields, unsaved "Second" Child is found.
  • "Second" Child is marked for insert, Insert query is prepared and is being put into the QueryQueue.
  • Continuing the merge process, Hibernate at some moment is trying to load the "Second" Child
  • But it was not yet inserted and the Excpetion is raised.
4

2 回答 2

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();
   }

}

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

于 2014-12-08T13:57:24.690 回答
1

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

@Transactional
 @NotNull
 protected S save(@NotNull S entity)
 {
    return getDao().save(entity);
 }
于 2015-01-05T15:21:26.667 回答