这个问题的根源是,什么会导致同步失败?这是一条通用消息,仅表示“出了点问题”,还是会话本身确实有问题? 有一些具有相似标题的线程,但似乎没有一个真正解决为什么 hibernate 无法同步会话,这只是人们忽略的错误消息的一部分。
我的具体案例/详细信息(尽管它与上述问题确实相切):
在数据导入期间(20-120 分钟),我正在进行大量处理。直到整个域对象集被构建并验证一致性后,持久性才开始。在这段时间里,我构建了大约 200,000 个域对象。在该过程结束时,它会在它们之间循环,将它们全部保存到数据库中,并(出于性能原因)在每 50 或 100 个对象后刷新/清除会话。一旦持久化开始,域对象就不会改变。
这一切都发生在单个服务调用、单个事务中。我也无法在我的测试系统上重现它,它只发生在生产中。
我正在使用domainObj.save()
而不是session.saveOrUpdate(domainObj)
,我唯一一次手动触摸会话是在一组更新后刷新/清理它:
def session = sessionFactory.currentSession
session.flush()
session.clear()
这是抛出异常的地方。
同步失败消息之后立即是(可能是结果,但可能与原因有关):
Could not execute JDBC batch update; SQL [insert into domainB(field1, field2, etc) values (?, ?, ?)];
nested exception is org.hibernate.exception.ConstrainViolationException: Could not execute JDBC batch update
我意识到这个 ConstrainViolation(是的,“constrain”而不是“constraint”)似乎是一个数据错误,但是数据集一直在工作,并且没有更改导入文件或代码,就开始抛出这个错误。它还在其他系统上继续工作,所以我已经在一定程度上排除了数据错误。
由于对象关系的性质,我几乎可以肯定相同的对象会被多次保存。这是性能改进的另一个地方,但我认为是无关的,因为一旦对象被保存,它应该分配它的 ID,并且重新保存不应该导致错误。
在这一点上我已经离题了,我不希望有人为我解决我的问题,但希望有人明确了解同步会话而不是“你确定你没有插入重复数据吗? " 因为我尽可能确定(使用受约束的唯一字段作为查找要保存的域对象的键来迭代 Hashmap.keySet())。