简而言之:
当我尝试将新(未保存)实体添加到已保存父对象的一对多集时,在父实体上调用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中似乎都是正确的,但事实上它会导致以下问题:
答案 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);
}