【问题标题】:Hibernate batching operation not working as expected休眠批处理操作未按预期工作
【发布时间】:2011-05-19 12:13:05
【问题描述】:
我有一个包含以下字段的 Person 类-
id、hashedId、描述
id是序列生成的主键,hashedId不为空。
我执行以下操作:
- session.saveOrUpdate(person)
- person.setHashedId(hash(person.getId()))
ID 是在数据库中自动生成的。当我这样做时,我不应该期望只有 2 个语句
- 选择获取下一个序列ID(人物ID)
- Insert 以插入人员记录?
但是,它正在尝试在第 1 步之后(当然是在最终事务提交期间)使用 null hashedId 插入 - 我得到一个违反约束的错误 - HashedId 不能为 null。
【问题讨论】:
标签:
database
hibernate
postgresql
orm
【解决方案1】:
HashedId 字段是从 ID 派生的,对吧?我假设基于廉价的功能?那么在这种情况下,您真的需要将该字段保留在数据库中吗?您是否直接在查询中使用它?
你不能让 getHashedId() 方法总是返回 hash(this.id) 吗?这样您就不会在数据库中拥有 hashedId 字段并且您不必管理它 - 因为它只是根据 id 推断出来的。
希望这会有所帮助。
【解决方案2】:
当您调用Session.save() 或类似名称时,Hibernate 将立即生成 ID 并执行插入操作,而不是简单地将其排队等待稍后保存。因此,元素在插入之前分配其 ID 是没有间隙的。对于“身份”ID生成策略,无论如何都完全不可能将它们分开......
根据我的经验,处理这种情况的最安全和最简单的方法是使用拦截器(或者可能是 EventListener?)来捕获正在插入且未设置 hashedId 属性的实体,并在保存之前生成它。这有点令人不快,但恕我直言,这比将 ID 生成拉到应用程序代码中要好。
这是一个示例,其中我生成了新 Ticket 实体的“引用”属性(使用拦截器):
public boolean onSave(Object entity, Serializable id, Object[] state, String[] propertyNames,
Type[] types) {
boolean changed = super.onSave(entity, id, state, propertyNames, types);
if (entity instanceof Ticket) {
for (int i = 0; i < propertyNames.length; i++) {
if (propertyNames[i].equals("reference") && state[i] == null) {
state[i] = generateTicketReference((Integer) id);
changed = true;
}
}
}
return changed;
}