我正在尝试使用命令模式允许我的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/

10-12 15:28