私は次のコードを持っています:
@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の警告が消えます...なぜですか?
しかし、このコードはSpring4.3.20で正しく機能します。このルールはSpring4.3.20で実際のものですか?
はい。 SonarLintは正しいです。自己呼び出しでは、_@Transactional
_を有効にすることはできません。 Spring5でも変更されません。これがSpringAOPの仕組みです( docs を参照)。コードが機能するのは、おそらくitemDao
内で別のトランザクションを開始したためです(ItemDao#addItems()
に別の_@Transactional
_がマークされている可能性があります)。
2番目のメソッドをpackage-privateとして作成すると、SonarLintの警告が消えます...なぜですか?
理由はわかりません。多分それはバグです。この rule で述べたように、プライベートメソッドで_@Transactional
_をマークすると警告が表示されます。
トランザクションの必要がない場合は、正しく機能する可能性があります。 @Transactional
は、springによって作成されたプロキシで呼び出されたメソッドでのみ機能します。つまり、@Service
または他のBeanを作成すると、外部から呼び出されたメソッドはトランザクションになります。 Bean内から呼び出された場合、プロキシオブジェクトを通過しないため、何も起こりません。
詳細については、 この質問 を参照してください。