2012-03-03 51 views
9

我很困惑会议和交易。我基本上都没有看到两者有什么关系,而且我很困惑什么时候使用其中一种。Grails:未刷新的会话和回滚事务之间有什么区别?

未刷新的会话和未提交的事务之间有什么区别?

我甚至不知道怎么问什么我不知道......是否有一个资源可以提供常见会话和事务情况的良好示例,以便我可以看到差异?

回答

18

Hibernate中的事务与JDBC中的事务几乎相同。当您从DataSource获得Connection时,它默认为autocommit = true,因此对于更改为autocommit = false的事务。这样,只有在明确提交时才会在数据库中进行更改,而不是每次执行更新。

Hibernate的Session做了几件事情,但在这种情况下,它的功能是作为第一级缓存。它使用一种称为“事务性写入后备”的概念来提高性能,以便对缓存中的更改进行排队,并在必要时将其推送到数据库。因此,例如,如果您检索持久性实例并在复杂的多方法工作流中对其进行更改,其中每个方法可能不会发生任何更改或几次更改,则只需要一条更新SQL语句,以便Hibernate一直等到需要将它们聚合在一起。这与您是否在交易中运行无关 - 总会发生。

在活动事务期间,会话高速缓存和活动事务聚集在一起的地方。由于Hibernate尽可能长时间地等待刷新更改,如果您不在事务中并且刷新,那么更改将立即在数据库中持久化。所以这是一个可以减少数据库写入次数的性能优化。但是,如果您正在处理事务并刷新会话,则会将更改推送到数据库。但数据库保留其事务队列中的更改。因此,即使它们在数据库中,但在您提交事务之前,它们对其他连接都不可见。

理想情况下,不会有任何显式刷新,并且事务提交将在提交之前触发刷新,并且这会同时最小化您需要转到数据库的次数,并保持未提交的更改对其他调用者不可见。但是,您可以根据需要多次冲洗。

有一件事会导致Hibernate代表您自动刷新查询。正如我所说的,你可以对持久化实例进行很多更改(甚至删除它们),它们只会在会话高速缓存中排队。但是,如果您运行查询(动态查找器,标准,HQL等),Hibernate无法知道排队的更改是否会影响您的查询。所以这是悲观的,并确保一切都是一致的查询。数据库将为您的查询使用刷新但未提交的数据并返回预期结果。这就是我们建议您在自定义域类验证程序中执行查询时使用withNewSession方法的原因,因此在验证期间不会导致当前会话刷新,这可能会导致奇怪的行为。

相关问题