内部有 try/catch 的 foreach 循环中的延迟加载异常
Lazy Load Exception in a foreach loop with try/catch inside
我有以下代码:
User
是一个 Hibernate 域。
for(User user : users) {
try {
function()
//log the user content
} catch(Exception ex) {
log.warn("Exception " + ex.toString() + ". Continue...")
}
}
User
的某些字段正在延迟加载。在 function()
抛出异常的情况下,延迟加载会抛出 no Session
异常,因此用户内容记录被破坏。
而
for(int i=0; i<users.size();++i) {
var user = users.get(i)
try {
function()
//log the user content
} catch(Exception ex) {
log.warn("Exception " + ex.toString() + ". Continue...")
}
}
工作正常。
我真的需要了解这的根本原因,所以任何提示都将不胜感激。
很难说到底发生了什么,但可能在某个时候抛出异常,这会清除 Hibernate 会话,并且下次访问代理时它会抛出 LazyInitializationException
。
参见例如https://docs.grails.org/5.1.7/guide/single.html#declarativeTransactions
[Transactional] methods are wrapped in a transaction and automatic rollback occurs if a method throws an exception (both Checked or Runtime exceptions)
https://docs.grails.org/5.1.7/guide/single.html#transactionsRollbackAndTheSession 提到
When a transaction is rolled back the Hibernate session used by GORM is cleared. This means any objects within the session become detached and accessing uninitialized lazy-loaded collections will lead to a LazyInitializationException.
我想这也是您的情况。我不确定为什么它不会出现在您发布的第二个代码片段中,也许 users.get(i)
代码实际上再次从您的数据库中获取对象。
其他解决方法包括:
- 重写您的代码,以便不抛出异常并保留会话
- 为每个对象使用单独的会话 (
User.withNewSession { ... }
) -> 不利于性能
- re-fetch 异常发生后的对象(如果你必须经常这样做也不是最佳的)
我有以下代码:
User
是一个 Hibernate 域。
for(User user : users) {
try {
function()
//log the user content
} catch(Exception ex) {
log.warn("Exception " + ex.toString() + ". Continue...")
}
}
User
的某些字段正在延迟加载。在 function()
抛出异常的情况下,延迟加载会抛出 no Session
异常,因此用户内容记录被破坏。
而
for(int i=0; i<users.size();++i) {
var user = users.get(i)
try {
function()
//log the user content
} catch(Exception ex) {
log.warn("Exception " + ex.toString() + ". Continue...")
}
}
工作正常。 我真的需要了解这的根本原因,所以任何提示都将不胜感激。
很难说到底发生了什么,但可能在某个时候抛出异常,这会清除 Hibernate 会话,并且下次访问代理时它会抛出 LazyInitializationException
。
参见例如https://docs.grails.org/5.1.7/guide/single.html#declarativeTransactions
[Transactional] methods are wrapped in a transaction and automatic rollback occurs if a method throws an exception (both Checked or Runtime exceptions)
https://docs.grails.org/5.1.7/guide/single.html#transactionsRollbackAndTheSession 提到
When a transaction is rolled back the Hibernate session used by GORM is cleared. This means any objects within the session become detached and accessing uninitialized lazy-loaded collections will lead to a LazyInitializationException.
我想这也是您的情况。我不确定为什么它不会出现在您发布的第二个代码片段中,也许 users.get(i)
代码实际上再次从您的数据库中获取对象。
其他解决方法包括:
- 重写您的代码,以便不抛出异常并保留会话
- 为每个对象使用单独的会话 (
User.withNewSession { ... }
) -> 不利于性能 - re-fetch 异常发生后的对象(如果你必须经常这样做也不是最佳的)