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