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:
I also encountered this problem. Notice your saveOrUpdate method is not starting a transaction. The solution to this is to start a transaction and make sure to commit your transaction after calling session.update or session.saveOrUpdate.
Update your saveOrUpdate method like this:
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();
}
}
This thread gave me a hint to the solution to your problem and your saveOrUpdate method verifies the missing transaction.