Grails:未刷新的会话和回滚的事务有啥区别?
Posted
技术标签:
【中文标题】Grails:未刷新的会话和回滚的事务有啥区别?【英文标题】:Grails: What is the difference between an unflushed session and a rolled back transaction?Grails:未刷新的会话和回滚的事务有什么区别? 【发布时间】:2012-03-21 11:27:46 【问题描述】:我对会话和交易感到很困惑。我基本上不明白同时使用两者有什么意义,而且我很困惑何时使用其中一个。
未刷新的会话和未提交的事务有什么区别?
我什至不知道如何问我不知道的问题...是否有资源可以提供常见会话和事务情况的良好示例,以便我可以看到差异?
【问题讨论】:
【参考方案1】:Hibernate 中的事务通常与 JDBC 中的事务非常相似。当您从DataSource
获得Connection
时,它默认为autocommit=true,因此对于更改为autocommit=false 的事务。这样,只有在显式提交时才会在数据库中进行更改,而不是每次进行更新时。
Hibernate 的Session
做了几件事,但在这种情况下,它的功能是作为一级缓存。它使用一种称为“事务性后写”的概念来提高性能,以在该缓存中排队更改,并仅在必要时将它们推送到数据库。因此,例如,如果您检索一个持久实例并在一个复杂的多方法工作流中对其进行更改,其中每个方法可能不做任何更改或几个更改,则只需要一个更新 SQL 语句,因此 Hibernate 等待直到有必要将它们聚合在一起。这与您是否在事务中运行无关 - 总是会发生。
会话缓存和活动事务聚集在一起的地方是在活动事务期间刷新。由于 Hibernate 尽可能长时间地等待刷新更改,如果您不在事务中并且您刷新,更改将立即在数据库中持久化。所以这是减少数据库写入次数的性能优化。但是,如果您在事务中并且刷新会话,则确实会将更改推送到数据库。但是数据库将更改保留在其事务队列中。因此,即使它们在数据库中,在您提交事务之前,它们对其他连接都是不可见的。
理想情况下,不会有任何显式刷新,并且事务提交将在提交之前触发刷新,这既可以最大限度地减少您需要访问数据库的次数,又可以保持未提交的更改对其他调用者不可见。但是您可以根据需要多次冲洗。
会导致 Hibernate 代表您自动刷新的一件事是查询。正如我所说,您可以对持久实例进行许多更改(甚至删除它们),它们只会在会话缓存中排队。但是如果您运行查询(动态查找器、条件、HQL 等),Hibernate 无法知道排队的更改是否会影响您的查询。因此,它是悲观的并刷新以确保查询的所有内容都是一致的。数据库将为您的查询使用刷新但未提交的数据并返回预期结果。这就是我们建议您在自定义域类验证器中执行查询时使用withNewSession
方法的原因,这样您就不会在验证期间导致当前会话刷新,这可能会导致奇怪的行为。
【讨论】:
以上是关于Grails:未刷新的会话和回滚的事务有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章