通过spring注释进行交易 - 只读或不读?

时间:2011-11-24 13:22:10

标签: spring transactions readonly

我的项目代码与此类似

@Transactional(readOnly = true)
public void tt() {
    dd();
}

@Transactional()
public void dd() {
    gg();
}

@Transactional(readOnly = true)
public void gg() {

}

函数dd由其他只读事务函数使用,而不是只读函数。假设事务应该从执行tt扩展到gg - dd中的操作是否为只读事务?

3 个答案:

答案 0 :(得分:6)

在这个特定的例子中,你的问题没有实际意义。

dd()tt()的调用不会通过代理边界,因此不会向dd()应用任何事务建议(因为它是在同一实例内的调用)。与来自gg()的{​​{1}}的来电相同。因此,只有从外部到dd()的调用实际上是事务建议的(在您的情况下,使用tt())并且这将是将在整个调用链中使用的事务。

在一般情况下,请阅读@melihcelik暗示的文档 - 它解释了行为。

答案 1 :(得分:3)

如果您正在执行get / select并且没有进行任何更改,请使用@Transactional(readoOnly = true),这意味着不会应用任何锁定(这更有效)。

对于我使用的更新/插入/删除/保存/合并(当需要锁定时):

@Transactional(propagation=Propagation.REQUIRED, rollbackFor=Exception.class)

答案 2 :(得分:3)

Spring的AbstractPlatformTransactionManager有一个名为validateExistingTransaction的属性来控制这种行为。 Javadoc说:

  

当参与现有交易时(例如,PROPAGATION_REQUIRES或PROPAGATION_SUPPORTS遇到现有交易),此外部交易的特征甚至将应用于内部交易范围。验证将检测内部事务定义上的不兼容隔离级别和只读设置,并通过抛出相应的异常来拒绝参与。

由于Spring @Transactional注释的默认传播为REQUIRED且默认验证策略为false,因此我希望Spring在只读模式下使用从tt方法调用创建的现有事务。

如果您想要一个只读事务,那么您必须使用以下方法注释您的方法:

  @Transactional(propagation=Propagation.REQUIRES_NEW, readOnly=true)