我正在尝试使用命令模式允许我的Web层在单个事务的上下文中与Hibernate实体一起工作(从而避免延迟加载异常)。但是,我现在对如何处理交易感到困惑。
我的命令调用以@Transactional
批注进行批注的服务层方法。其中一些服务层方法是只读的-例如@Transactional(readOnly=true)
-有些是读/写的。
我的服务层公开了一个命令处理程序,该命令处理程序代表Web层执行传递给它的命令。
@Transactional
public Command handle( Command cmd ) throws CommandException
我以为我可以使命令处理程序的
handle()
方法具有事务性。这就是造成困惑的地方。如果命令的实现调用了多个服务层方法,则命令处理程序将无法知道命令内调用的操作是只读,读/写还是组合操作在两个中。我不了解此示例中的传播方式。如果我将
handle()
方法设置为readOnly=true
,那么,如果该命令随后调用了一个用@Transactional(realOnly=false)
注释的服务层方法,会发生什么?非常感谢您对此有所了解,并欢迎您提出宝贵意见。
安德鲁
最佳答案
首先,由于Spring本身并不执行持久性,因此无法指定readOnly
的确切含义。该属性仅是提供者的提示,其行为取决于(在这种情况下)Hibernate。
如果您将readOnly
指定为true
,则刷新模式将在当前的休眠 session 中设置为 FlushMode.NEVER
,从而阻止该 session 提交事务。
此外,将在JDBC连接上调用 setReadOnly(true),这也是对基础数据库的提示。如果您的数据库支持它(很可能会这样做),则其效果基本上与FlushMode.NEVER
相同,但是它更强大,因为您甚至无法手动刷新。
现在让我们看看事务传播是如何工作的。
如果未将readOnly
显式设置为true
,则将具有读/写事务。根据事务属性(例如REQUIRES_NEW
),有时您的事务在某个时候被挂起,开始新事务并最终提交,然后恢复第一笔事务。
好,我们快到了。让我们看看是什么将readOnly
带入这种情况。
如果读/写事务中的方法调用需要 readOnly 事务的方法,则应暂停第一个方法,因为否则将在第二种方法的结尾进行刷新/提交。
相反,如果您从 readOnly 事务中调用需要读/写的方法,则第一个方法将被挂起,因为它无法刷新/提交,而第二个方法则需要它。
在 readOnly-to-readOnly 和读/写到读/写的情况下,不需要暂停外部事务(显然,除非另外指定传播)。
关于spring - Spring @Transactional只读传播,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/1614139/