对于正确Map为Hibernate实体类的MariaDB表的简单批处理更新,通过Hibernate进行简单更新会产生以下错误
org.hibernate.StaleStateException: Batch update returned unexpected row count from update
每个表记录都由Entity
类建模,这是一个简单的POJO,需要更新(如果它已经存在)或作为新对象插入(如果它在表中不存在),它有一个主id
字段(不是自动递增的)和一些其他值,都是标量。
public static void update(Set<Long> ids) {
Session session = createSession();
Transaction t = session.beginTransaction();
try {
for (Long id : ids) {
Entity entity = session.get(Entity.class, id);
if (entity == null) {
entity = new Entity();
}
entity.setId(id);
// Other entity value settings
session.saveOrUpdate(entity);
}
transaction.commit();
} catch (Exception e) {
transaction.rollback();
} finally {
session.close();
}
}
在Hibernate中实现上述操作的正确方法是什么?
1条答案
按热度按时间6ojccjat1#
您以这种方式使用saveOrUpdate(),Hibernate通过自己的逻辑决定什么是新的( transient )对象,什么是旧的(持久化)对象,并根据这一点相应地执行
save()
或update()
方法。在下列情况下,Hibernate会假设执行严修是未储存的暂时执行严修:
null
。null
。unsaved-value
,标识符属性的值匹配。unsaved-value
属性也可用于版本和时间戳Map元素。org.hibernate.Interceptor
,并在程式码中检查执行严修之后,从Interceptor.isUnsaved()
传回Boolean.TRUE
。**否则:**实体将被确定为已保存的持久实体
在您的示例中,Hibernate没有确定新的( transient )对象,因此,对它执行
update()
方法。它生成UPDATE
而不是INSERT
语句。UPDATE
语句对不存在的记录返回零个更新的记录,因此这就是您的异常的原因。**解决方案:**为新实体显式使用save()方法:
update()
方法不需要显式调用。事务持久性示例(即由会话加载、保存、创建或查询的对象)可以由应用程序操作,并且当会话为flushed
时,对持久性状态的任何更改都将被持久化。根据文档。