我正在尝试本地化以下代码片段中的错误:
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]
我认为删除数据库条目时会发生冲突,而迭代器不会通过调用 it.remove() 进行调整。
BookLog 不引用任何表,因此其映射很简单。
最佳答案
由于Query.interate()
返回代理迭代器,因此仅获取实体的id
。
Executes 1+N SQL queries. The first query only returns the identifier of all the records and when the returned iterator is iterated then each time a separate SQL query is executed that contains a WHERE clause like WHERE id=N. If the records are present in cache then the first query is executed and the rest N queries are not executed and records are obtained from cache.
所以这是并发修改问题。当您执行查询时
for (Iterator it = bookLogs.iterate(); it.hasNext();) {
给定的 BookLog
存在,其 id
返回到迭代器中。迭代时,对于每个
bookNo = bookLog.getNo()
执行单独的SELECT
查询,但此时整个表可能已被另一个并发操作修改。给定 id 的行不再存在,并抛出异常。
为了避免这种情况,您必须使用适当的transaction-isolation
或使用Query.getResultList()
。这将返回单个查询中的所有结果。但是,(再次)不能保证当您尝试删除
返回的实体时,它仍然位于数据库中。
关于java - 查询迭代时出现 org.hibernate.ObjectNotFoundException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29388855/