查询迭代时的org.hibernate.ObjectNotFoundException

时间:2015-04-01 10:48:07

标签: java hibernate

我尝试本地化以下代码段中的错误:

Query bookLogs = session.createQuery("FROM BookLog log");
for (Iterator it = bookLogs.iterate(); it.hasNext();) {
  BookLog bookLog = (BookLog) it.next();
  bookNo = bookLog.getNo();
  ...
  session.delete(bookLog);
  session.flush();
}

在bookLog.getNo()中不常发生以下异常:

org.hibernate.ObjectNotFoundException: No row with the given identifier exists: [de.store.Books.BookLog#2343]

我认为在删除db条目时会发生冲突,而迭代器不会通过调用它来调整.remove()。

BookLog不引用任何表格,因此其映射很简单。

1 个答案:

答案 0 :(得分:0)

Query.interate()返回代理迭代器时,只有id个实体被提取。

  

执行1 + N个SQL查询。第一个查询只返回所有记录的标识符,并且当迭代返回的迭代器时,每次执行包含WHERE id = N的WHERE子句的单独SQL查询。如果记录存在于缓存中,则执行第一个查询,不执行其余N个查询,并从缓存中获取记录。

所以这是并发修改问题。在执行查询时

for (Iterator it = bookLogs.iterate(); it.hasNext();) {

给定BookLog并将其id返回到迭代器中。在迭代时,为每个

 bookNo = bookLog.getNo()

执行单独的SELECT查询,但在此时,整个表可能已被另一个并发操作修改。给定id的行不再存在,并抛出异常。 为避免这种情况,您必须使用正确的transaction-isolation或使用Query.getResultList()。这将在单个查询中返回所有结果。但是,无法保证(再次)当您尝试delete返回的实体时,它仍然会在数据库中。