根据 Spring javadoc
@Transactional(propagation = Propagation.SUPPORTS)
支持当前事务,如果没有则以非事务方式执行 存在。类似于同名的 EJB 事务属性。
看来我可以只声明非事务性的方法并完成它,所以我的问题是。
任何人都可以举一个现实世界的例子/场景,其中支持实际上很有用吗?
我能想到的最简单的例子是将一些内容发送到 JMS 服务器的方法。 如果您处于事务上下文中,您希望将消息耦合到事务范围。 但是,如果还没有正在运行的事务,为什么还要调用事务服务器并启动一个事务服务器来执行一次性消息呢?
请记住,这些可以在 API 和实现上声明。 因此,即使对于您的用例来说,将其放在那里和不放任何东西之间没有太大区别,它仍然为 API 作者增加了价值,以指定事务中可以包含哪些操作,而不是可能调用的操作不参与交易的外部系统。
这当然是在 JTA 背景下。 在事务仅限于资源本地物理数据库事务的系统中,该功能实际上并没有太多实际用途。
它与选择操作上的
readOnly=true
事务标志是很好的一对,尤其是在使用 ORM 时:
@Transactional(readOnly = true, propagation=Propagation.SUPPORTS)
public Pojo findPojo(long pojoId) throws Exception {
return em.find(Pojo.class, pojoId);
}
在这种情况下,如果还没有用于执行选择操作的交易,请确保不要支付创建新交易的费用。
尽管如果您已经处于这个思考过程中,您甚至可能会考虑完全放弃事务方面:
public Pojo findPojo(long pojoId) throws Exception {
return em.find(Pojo.class, pojoId);
}
根据这个问题使用Propagation.SUPPORTS提高只读操作的性能你不应该使用Propagation.SUPPORTS设置只读事务:
目前还不清楚这一变化是否会真正提高性能。这其中有多个方面。首先,链接的文章已经过时并且存在令人难以置信的缺陷,因为它过度简化了事情。如果您愿意,我可以详细介绍,但我现在就先到此为止。这里有很多因素会影响执行性能。如果没有正在进行的事务,则 readOnly 标志不会传播到 JDBC 驱动程序(这将导致许多数据库的优化未被应用),您也不会在 Spring 的 JPA 资源管理代码中应用优化,例如显式关闭刷新,这 - 如果应用 - 如果您读取大量数据,可以显着提高性能。
使用
Propagation.SUPPORTS
,您可以在抛出异常时触发设置仅回滚标志。例如,在下面的代码中,虽然有一个 catch 块,但是当离开 UnexpectedRollbackException
块时,将会抛出 txRequired
。
TransactionTemplate txRequired = new TransactionTemplate(platformTransactionManager);
TransactionTemplate txSupports = new TransactionTemplate(platformTransactionManager);
txRequired.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
txSupports.setPropagationBehavior(TransactionDefinition.PROPAGATION_SUPPORTS);
//prints 'Exception handled' and then throws UnexpectedRollbackException
txRequired.executeWithoutResult(tx -> {
try {
txSupports.executeWithoutResult(tx2 -> {
throw new RuntimeException();
});
} catch (Exception ex) {
System.out.println("Exception handled");
}
});
下面的代码显然不会抛出任何异常。唯一的区别是缺少
PROPAGATION_SUPPORTS
块。
txRequired.executeWithoutResult((tx) -> {
try {
throw new RuntimeException();
} catch (Exception ex) {
System.out.println("Exception handled");
}
});
@Transactional(propagation = Propagation.SUPPORTS)
的一种用法是用另一个传播值覆盖从接口继承的声明。