只是为了理解Spring事务的工作原理我想知道在下面的情况下会发生什么情况,其中一个标记为@Transactional
的方法调用另一个标记为@Transactional
的方法。
假设配置使用所有默认设置。
@Service("myService")
@Transactional
public MyService{
public void myServiceMethod(){
myDAO.getSomeDBObjects();
}
}
@Repository("myDAO")
@Transactional
public MyDAOWithUsesBeyondMyService{
public void getSomeDBObjects(){...}
}
现在,如果我要输入MyService.myServiceMethod()
,那么显然会启动一项交易。然后,钻进myDAO.getSomeDBObjects()
会发生什么?交易已经存在的事实会导致没有新的交易产生,或者我是否在这里创建了两笔交易?
关于传播的文档(如下所述)似乎涵盖了这一点,但我想验证我的理解,这对我的处女大脑来说有点多了解一下。
传播:通常是所有代码 在事务范围内执行 将在该交易中运行。然而, 你可以选择指定 在a。的情况下的行为 事务方法在执行时执行 事务上下文已存在。 例如,代码可以继续运行 在现有的交易中( 常见情况);或现有的 交易可以暂停和新的 交易创建。春天提供所有 事务传播选项 熟悉EJB CMT。阅读 交易的语义 在Spring中传播,参见章节 10.5.7,“交易传播”。
答案 0 :(得分:39)
两个答案:
a)不要这样做。在服务层或dao层中使用@Transactional
,但不能同时使用两者(服务层是通常的选择,因为您可能需要每个服务方法一个事务)
b)如果您这样做,会发生什么取决于propagation
注释的@Transactional
属性,并在本节中进行了描述:10.5.7 Transaction propagation。基本上:PROPAGATION_REQUIRED
表示同一事务将用于两种方法,而PROPAGATION_REQUIRES_NEW
启动新事务。
关于您的评论:
当然我一直在阅读并意识到,由于我正在使用代理,第二种方法不会由事务代理管理,因此它就像任何其他方法调用一样。
在你的情况下情况并非如此(只有两种方法都属于同一类)。
如果bean有方法a
和b
以及a
调用b
,则会在实际方法上调用b
,而不是代理,因为它是从代理中调用的(bean不知道它代理了外部世界)。
proxy bean
a() --> a()
|
V
b() --> b()
然而,在你的情况下,服务会有一个注入的dao对象,它本身就是一个代理,所以你会遇到这样的情况:
proxy bean
service a() --> a()
|
/---------/
|
V
dao b() --> b()