Spring 4.3 从非事务方法调用@Transactional 方法
Calling @Transactional method from non-transactional method in Spring 4.3
我有以下代码:
@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 工具声明 "Methods should not call same-class methods with incompatible "@Transactional" values" (https://rules.sonarsource.com/java/RSPEC-2229)
但是这段代码在 Spring 4.3.20 中可以正常工作。此规则适用于 Spring 4.3.20 吗?
P.S。有趣的是,如果我将第二种方法设为包私有,SonarLint 警告就会消失...为什么?
But this code works correctly in Spring 4.3.20. Is this rule actual
for Spring 4.3.20?
是的。 SonarLint 是正确的。自调用不能使@Transactional
生效。即使在 Spring 5 中它也不会改变。这就是 Spring AOP 的工作方式(参考 docs)。您的代码很可能有效,因为您在 itemDao
内开始了另一项交易(可能是您在 ItemDao#addItems()
上标记了另一个 @Transactional
)。
if I make the second method as package-private, the SonarLint warning
disappears... Why?
不知道为什么。也许这是一个错误。正如这个 rule 中提到的,它应该在私有方法中标记 @Transactional
时给你警告。
在不需要交易的情况下,它可能会正常工作。 @Transactional
仅适用于在 spring 创建的代理上调用的方法。这意味着,当您创建 @Service
或其他 bean 时,从外部调用的方法将是事务性的。如果从 bean 中调用,则不会发生任何事情,因为它不通过代理对象。
有关详细信息,请参阅 this question。
我有以下代码:
@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 工具声明 "Methods should not call same-class methods with incompatible "@Transactional" values" (https://rules.sonarsource.com/java/RSPEC-2229)
但是这段代码在 Spring 4.3.20 中可以正常工作。此规则适用于 Spring 4.3.20 吗?
P.S。有趣的是,如果我将第二种方法设为包私有,SonarLint 警告就会消失...为什么?
But this code works correctly in Spring 4.3.20. Is this rule actual for Spring 4.3.20?
是的。 SonarLint 是正确的。自调用不能使@Transactional
生效。即使在 Spring 5 中它也不会改变。这就是 Spring AOP 的工作方式(参考 docs)。您的代码很可能有效,因为您在 itemDao
内开始了另一项交易(可能是您在 ItemDao#addItems()
上标记了另一个 @Transactional
)。
if I make the second method as package-private, the SonarLint warning disappears... Why?
不知道为什么。也许这是一个错误。正如这个 rule 中提到的,它应该在私有方法中标记 @Transactional
时给你警告。
在不需要交易的情况下,它可能会正常工作。 @Transactional
仅适用于在 spring 创建的代理上调用的方法。这意味着,当您创建 @Service
或其他 bean 时,从外部调用的方法将是事务性的。如果从 bean 中调用,则不会发生任何事情,因为它不通过代理对象。
有关详细信息,请参阅 this question。