gpt4 book ai didi

hibernate - Grails 程序化事务处理

转载 作者:行者123 更新时间:2023-12-02 13:52:27 24 4
gpt4 key购买 nike

我的 Grails 应用程序有一个服务方法,可以更新来自 last.fm 的 Web 服务的艺术家列表。

@Transactional(propagation = Propagation.NOT_SUPPORTED)
void updateLastFmArtists(Range idRange = null) {

Artist.list().each { Artist artist ->

// We could be updating a lot of artists here, the process could take up
// to an hour and we don't want to wrap all that in a single transaction
Artist.withTransaction { status ->
try {
updateArtistInfo(artist)

} catch (IOException ex) {
status.setRollbackOnly()
}
}
}
}

每个艺术家都在其自己的事务中更新,如果 IOException 应回滚被抛出。但是,我注意到以下行为:

如果更新艺术家的尝试抛出 IOException - 导致事务回滚 - 那么下一个艺人的更新总是因为下面的错误而失败

org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: org.example.Artist.topTracks, no session or session was closed



如果我更改上面的代码以便每个艺术家在其自己的 session 中更新,这似乎可以解决问题,
   Artist.withNewSession { session ->
Artist.withTransaction { status ->
try {
updateArtistInfo(artist)

} catch (IOException ex) {
status.setRollbackOnly()
}
}
}

但我不明白为什么我需要这样做,即为什么回滚事务似乎会关闭 session ?

最佳答案

回滚使 session 不可用是正常的,因为它是一个不可恢复的错误,就像所有 Hibernate 异常一样。例如,参见类 ObjectNotFoundException 的 javadoc :

/*
* ...
*
* Like all Hibernate exceptions, this exception is considered
* unrecoverable.
*
*/

原因是 session 是数据库和内存中对象之间的状态同步器组件。处理数据库回滚的方法是回滚内存中对象的更改。

由于此功能难以实现且用途有限,因此决定使此类异常不可恢复。

您可以 try catch 它并继续使用 session ,但不能保证 session 将处于一致状态。

编辑:

这里是除 Javadoc 之外的更多引用资料,可在 documentation 中找到。 :

An exception thrown by Hibernate means you have to rollback your database transaction and close the Session immediately (this is discussed in more detail later in the chapter). If your Session is bound to the application, you have to stop the application. Rolling back the database transaction does not put your business objects back into the state they were at the start of the transaction. This means that the database state and the business objects will be out of sync. Usually this is not a problem, because exceptions are not recoverable and you will have to start over after rollback anyway.



并且:

If the Session throws an exception, including any SQLException, immediately rollback the database transaction, call Session.close() and discard the Session instance. Certain methods of Session will not leave the session in a consistent state. No exception thrown by Hibernate can be treated as recoverable. Ensure that the Session will be closed by calling close() in a finally block.

关于hibernate - Grails 程序化事务处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21638706/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com