在视图中使用Open Session时,事务传播如何工作?

Dre*_*ter 7 java spring hibernate transactions

我对使用Hibernate的Spring中的事务传播感到困惑.我@Transactional在服务层方法上使用Spring 注释.有些被标记为'只读=真'.如果我的一个只读服务方法调用的方法不是只读的,我该如何处理?

我想我可以标记所有读写方法以支持REQUIRES_NEW传播,但这会导致我可能不想要的行为 - 即在只读方法被称为读写的情况下我只想要一个新事务方法.如果读写方法调用另一个读写方法,我就不需要新的事务.

考虑到所有这些因素,我不明白Open Session In View(OSIV)是如何工作的!当然,在Spring中使用OSIV,OpenSessionInViewFilter必须在调用服务方法之前启动事务.在这种情况下,必须定义事务是只读还是读写.但是,怎么知道呢?它不知道在服务层的覆盖下会发生什么.

我对这一切都完全处于黑暗中,并希望有人向我解释它!

ska*_*man 6

Hibernate会话的生命周期与事务的生命周期不同.两者可以相互重叠.

在这种情况下OpenSessionInViewFilter,这与事务完全无关,它只是在请求期间管理Hibernate会话的生命周期.调用Spring-transactional方法时,将启动一个新事务,并与hibernate会话关联,然后在方法退出时提交/回滚.然后,当请求完成时,过滤器将关闭会话.没有必要在会话的同时开始/完成交易.

至于你的read-only交易问题(这是一个完全不同的问题,顺便提一下),这只不过是对底层数据库的一个提示,即没有数据会被修改.我从未见过这有任何具体的影响,但它作为一种文档工具似乎比其他任何东西都更有用.


Ram*_*mon 3

在视图中打开会话并不要求整个请求发生在单个事务中,它仅意味着 Hibernate 会话绑定到服务请求的线程,并在每次请求中请求会话时重新使用。请记住,会话就像一张奇特的映射,它维护其范围内映射的所有对象的标识,可以在一个事务或多个事务中获取实际对象。

Session per Transaction 的模式实际上是OSIV 的替代方案。这种模式并不常见。

关于您的只读方法调用读写方法的问题,我想说您应该重新思考为什么要考虑这种只读方法,而实际上它可以写入数据。我认为,要么您排除只读部分并让读写方法调用只读方法,要么您停止将其视为只读(事实并非如此)。

仅仅因为一个事务被置于只读模式,并不意味着它将在会话 (OSIV) 的其余范围内保持只读模式。事实上,打开的会话范围内的后续事务甚至可能不会发生在同一个连接上。