Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 理解Spring事务——当一个事务性方法调用另一个事务性方法时会发生什么?_Java_Spring_Transactions - Fatal编程技术网

Java 理解Spring事务——当一个事务性方法调用另一个事务性方法时会发生什么?

Java 理解Spring事务——当一个事务性方法调用另一个事务性方法时会发生什么?,java,spring,transactions,Java,Spring,Transactions,为了理解Spring事务的工作原理,我想知道在下面的情况下会发生什么,其中一个标记为@Transactional的方法调用另一个标记为@Transactional的方法 假设配置使用所有默认设置 @Service("myService") @Transactional public MyService{ public void myServiceMethod(){ myDAO.getSomeDBObjects(); } } @Repository("myDAO") @T

为了理解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()
时会发生什么?事务已经存在的事实是否会导致没有新事务生成,或者我在这里创建了两个事务

关于传播的文档(下面引用)似乎涵盖了这一点,但我想验证一下我的理解,这对我的处女大脑来说是一个一次性理解的小问题

传播:通常,所有代码 在事务范围内执行 将在该事务中运行。然而, 您可以选择指定 发生以下情况时的行为: 事务方法在以下情况下执行: 事务上下文已存在。 例如,代码可以继续运行 在现有事务中(在 一般情况);还是现有的 可以挂起事务并创建新的 已创建事务。春天提供一切 事务传播选项的定义 熟悉EJBCMT。了解 事务的语义 在春季传播,请参见第节 10.5.7,“交易传播”

两个答案:

a) 不要这样做。在服务层或dao层中使用
@Transactional
,但不能同时使用两者(服务层是通常的选择,因为您可能希望每个服务方法有一个事务)

b) 如果执行此操作,则发生的情况取决于
@Transactional
注释的
传播
属性,本节对此进行了描述:。基本上:
PROPAGATION\u REQUIRED
意味着相同的事务将用于两种方法,而
PROPAGATION\u REQUIRES\u NEW
启动一个新事务

关于您的评论:

当然,我一直在阅读并意识到,在使用代理时,第二个方法不会由事务代理管理,因此它与任何其他方法调用一样

在您的情况下不是这样的(只有当两个方法都在同一个类中时)

如果一个bean有方法
a
b
,并且
a
调用
b
,那么
b
在实际的方法上被调用,而不是在代理上,因为它是从代理内部被调用的(一个bean不知道它被代理到外部世界)

然而,在您的情况下,服务会有一个注入的dao对象,它本身就是一个代理,所以您会遇到这样的情况:

           proxy      bean
service    a() -->    a()
                       |
             /---------/
             |                 
             V
dao        b() -->    b()

谢谢,是的,我不打算这样做,但是当我意识到我已经在服务类级别声明了@Transactional,并且服务的一个方法正在调用服务的另一个方法(都是Transactional)时,我突然想到了这个问题。当然,我一直在阅读并意识到,当我使用代理时,第二种方法不会由事务代理管理,因此它就像任何其他方法调用一样(这足以让新启动的大脑感到困惑)。:)但这让我很好奇,确保我理解了所有工作原理的细节,你已经很好地为我澄清了这一点。谢谢@大卫,我想你误解了代理的概念。阅读我的更新。你是绝对正确的,我的评论是错误的(事实上我在没有说的情况下改变了假设),但我理解你所说的,在所有这些之后,我认为整个事情现在已经在我的脑海中根深蒂固了。感谢您的更新和伟大的图表,我相信许多其他人会发现它在他们的搜索在未来有用@SeanPatrickFloyd您能看一下并提供您的专家建议吗?
           proxy      bean
service    a() -->    a()
                       |
             /---------/
             |                 
             V
dao        b() -->    b()