一尘不染

Spring @Transactional只读传播

spring

我正在尝试使用命令模式来允许我的Web层在单个事务的上下文中使用Hibernate实体(从而避免延迟加载异常)。但是,我现在对如何处理交易感到困惑。

我的命令调用带有@Transactional注释的服务层方法。这些服务层方法中的某些方法是只读的,例如@Transactional(readOnly=true)-,而某些方法是读/写的。

我的服务层公开了一个命令处理程序,该命令处理程序代表Web层执行传递给它的命令。

@Transactional
public Command handle( Command cmd ) throws CommandException

我认为我对使命令处理程序的handle()方法具有事务性是正确的。这就是造成混乱的地方。如果命令的实现调用了多个服务层方法,则命令处理程序将无法知道命令内调用的操作是只读,读/写还是组合操作在两个中。

我不了解此示例中的传播方式。如果我要创建该handle()方法readOnly=true,那么如果该命令随后调用带有注释的服务层方法,会发生什么情况@Transactional(realOnly=false)

非常感谢你对此有所了解,并欢迎你提出意见。


阅读 466

收藏
2020-04-12

共1个答案

一尘不染

首先,由于Spring本身并不执行持久性,因此无法指定readOnly确切含义。该属性仅是提供者的提示,其行为取决于(在这种情况下)Hibernate。

如果指定readOnlytrue,则刷新模式将设置为FlushMode.NEVER当前的Hibernate Session中的状态,以防止会话提交事务。

此外,将在JDBC连接上调用setReadOnly(true),这也是对基础数据库的提示。如果你的数据库支持它(很可能会这样做),则其效果与基本上相同FlushMode.NEVER,但是它更强大,因为你甚至无法手动刷新。

现在,让我们看看事务传播是如何工作的。

如果未明确设置readOnlytrue,则将具有读/写事务。根据事务属性(如REQUIRES_NEW),有时你的事务在某个时候被挂起,新的事务开始并最终提交,然后恢复第一笔事务。

好,我们快到了。让我们看看导致readOnly这种情况的原因。

如果读/写事务中的方法调用需要readOnly事务的方法,则应暂停第一个方法,因为否则将在第二个方法的末尾进行刷新/提交。

相反,如果再次从需要read / write的readOnly事务中调用方法,则第一个方法将被挂起,因为它无法刷新/提交,而第二个方法则需要该方法。

在readOnly-to-readOnly和读/写到读/写的情况下,不需要暂停外部事务(除非你另外指定传播,否则显然)。

2020-04-12