在Spring 4.3中从非事务方法中调用@Transactional方法

时间:2019-02-07 05:43:40

标签: java spring

我有以下代码:

@Service
public class ItemService {
    ...

    public void addItems(@Nonnull DocumentDTO dto) throws Exception {
        // some code that takes some time to process
        ...

        addItems(dto.getDocId(), items);
    }

    @Transactional
    public void addItems(long docId, @Nonnull List<Item> items) {
        itemDao.addItems(docId, items);
    }
}

第一个方法不是@Transactional,它使用@Transactional调用第二个方法。 SonarLint工具指出“方法不应使用不兼容的“ @Transactional”值调用同类方法”(https://rules.sonarsource.com/java/RSPEC-2229

但是此代码在Spring 4.3.20中可以正常工作。这条规则对Spring 4.3.20有用吗?

P.S。有趣的是,如果我将第二种方法设置为私有程序包,则SonarLint警告消失了……为什么?

2 个答案:

答案 0 :(得分:4)

  

但是此代码在Spring 4.3.20中可以正常工作。这条规则是真的吗   对于Spring 4.3.20?

是的。 SonarLint是正确的。自我调用无法使@Transactional生效。即使在Spring 5中也不会改变。这就是Spring AOP的工作方式(请参阅docs)。您的代码很有用,因为您在itemDao内启动了另一个事务(可能在@Transactional上标记了另一个ItemDao#addItems())。

  

如果我将第二种方法设为包私有,则SonarLint警告   消失了...为什么?

不知道为什么。也许是一个错误。如本rule所述,在私有方法中标记@Transactional时,它应该给您警告。

答案 1 :(得分:1)

在不需要交易时,它可能会正常工作。 @Transactional仅适用于在spring创建的代理上调用的方法。这意味着,当您创建@Service或其他bean时,从外部调用的方法将是事务性的。如果从Bean内部调用,则不会发生任何事情,因为它不会通过代理对象传递。

有关更多详细信息,请参见this question