2015-04-01 95 views
1

我想在下面的代码片段本地化错误:org.hibernate.ObjectNotFoundException在查询迭代

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] 

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

BookLog没有引用任何表格,其映射也相应简单。

+0

为什么你要投入迭代器对象来预订?相反,您可以尝试BookLog bookLog =(BookLog)it.next(); – Ramesh 2015-04-01 12:27:15

+0

抱歉,小错字。 – user3639982 2015-04-01 13:02:27

+0

是否因为你试图去除那些不在那里的东西?我想它会返回NULL – ha9u63ar 2015-04-01 13:07:49

回答

0

由于Query.interate()返回代理迭代器,只有id的实体正在获取。

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

所以这是并发修改问题。当您执行查询

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

给出BookLog存在及其id返回到迭代器。虽然迭代,对于每一个

bookNo = bookLog.getNo() 

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