web-dev-qa-db-ja.com

Spring4.3の非トランザクションメソッドから@Transactionalメソッドを呼び出す

私は次のコードを持っています:

@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を使用して2番目のメソッドを呼び出します。 SonarLintツールは、「メソッドは、互換性のない「@Transactional」値を持つ同じクラスのメソッドを呼び出すべきではない」と述べています( https://rules.sonarsource.com/Java/RSPEC-2229

しかし、このコードはSpring4.3.20で正しく機能します。このルールはSpring4.3.20で実際のものですか?

P.S.興味深いことに、2番目のメソッドをpackage-privateとして作成すると、SonarLintの警告が消えます...なぜですか?

3
serg kunz

しかし、このコードはSpring4.3.20で正しく機能します。このルールはSpring4.3.20で実際のものですか?

はい。 SonarLintは正しいです。自己呼び出しでは、_@Transactional_を有効にすることはできません。 Spring5でも変更されません。これがSpringAOPの仕組みです( docs を参照)。コードが機能するのは、おそらくitemDao内で別のトランザクションを開始したためです(ItemDao#addItems()に別の_@Transactional_がマークされている可能性があります)。

2番目のメソッドをpackage-privateとして作成すると、SonarLintの警告が消えます...なぜですか?

理由はわかりません。多分それはバグです。この rule で述べたように、プライベートメソッドで_@Transactional_をマークすると警告が表示されます。

7
Ken Chan

トランザクションの必要がない場合は、正しく機能する可能性があります。 @Transactionalは、springによって作成されたプロキシで呼び出されたメソッドでのみ機能します。つまり、@Serviceまたは他のBeanを作成すると、外部から呼び出されたメソッドはトランザクションになります。 Bean内から呼び出された場合、プロキシオブジェクトを通過しないため、何も起こりません。

詳細については、 この質問 を参照してください。

1
Andronicus