带@Transactional(propagation = Propagation.SUPPORTS) 的方法和不带@Transactional 的方法有什么区别?
What is the difference between a method with @Transactional(propagation = Propagation.SUPPORTS) and method without @Transactional?
方法与
有什么区别
@Transactional(propagation = Propagation.SUPPORTS)
和没有 @Transactional
的方法?
例如:
public class TEst {
@Transactional
public void methodWithTransaction1(){
methodWithSupportsTransaction();
}
@Transactional
public void methodWithTransaction2(){
methodWithoutTransactional();
}
@Transactional(propagation = Propagation.SUPPORTS)
public void methodWithSupportsTransaction(){
}
public void methodWithoutTransactional(){
}
}
除了the javadoc中关于同步的细微差别外,两者之间的区别在于,如果方法被注释为Transactional,事务代理会拦截方法调用,并将标记当前事务(如果有) , 作为 rollbackOnly 如果从该方法抛出运行时异常。
所以,让我们举个例子:
public class A {
@Autowired B b;
@Transactional
public void foo() {
try {
b.bar();
}
catch (RuntimeException e) {
// ignore
}
...
}
}
public class B {
// @Transactional(propagation = Propagation.SUPPORTS)
public void bar() {
throw new RuntimeException();
}
}
如果 none 还存在(需要传播),则调用 a.foo()
将启动事务。然后 b.bar() 将被调用并抛出异常。异常被 a.foo()
捕获,它继续执行,就好像什么也没发生一样。 a.foo()
结束时,事务将提交成功。
现在让我们取消注释 b.bar()
上的事务注释。如果 none 存在(需要传播),则调用 a.foo()
将启动事务。然后 b.bar() 将被调用并抛出异常。这个异常将被 B 周围的事务代理"intercepted",它将事务标记为 rollbackOnly。然后异常将传播到 A.a.foo()
。异常被 a.foo()
捕获,它继续执行,就好像什么也没发生一样。在 a.foo()
结束时,事务将被提交,但该提交将失败,因为事务已被标记为 rollbackOnly。 a.foo() 的调用者将得到一个 TransactionSystemException。
Spring 支持两种类型的事务管理 programmatic 和 declarative.
程序化事务管理:这种方式的事务需要由我们来处理。例如-
EntityTransaction tran = entityManager.getTransaction();
try {
tran.begin();
methodWithoutTransactional();
tran.commit();
} catch(Exception ex) {
tran.rollback();
throw ex;
}
声明式事务管理: 以这种方式,我们可以将事务管理代码从我们的业务逻辑中分离出来,只需使用注释或基于 xml 的配置。您已经在示例代码中完成了这些操作-
@Transactional
public void methodWithTransaction1(){
methodWithSupportsTransaction();
}
对于@Transactional注解,如果我们不定义传播类型,默认会应用PROPAGATION_REQUIRED。您可以找到文档 here.
方法与
有什么区别@Transactional(propagation = Propagation.SUPPORTS)
和没有 @Transactional
的方法?
例如:
public class TEst {
@Transactional
public void methodWithTransaction1(){
methodWithSupportsTransaction();
}
@Transactional
public void methodWithTransaction2(){
methodWithoutTransactional();
}
@Transactional(propagation = Propagation.SUPPORTS)
public void methodWithSupportsTransaction(){
}
public void methodWithoutTransactional(){
}
}
除了the javadoc中关于同步的细微差别外,两者之间的区别在于,如果方法被注释为Transactional,事务代理会拦截方法调用,并将标记当前事务(如果有) , 作为 rollbackOnly 如果从该方法抛出运行时异常。
所以,让我们举个例子:
public class A {
@Autowired B b;
@Transactional
public void foo() {
try {
b.bar();
}
catch (RuntimeException e) {
// ignore
}
...
}
}
public class B {
// @Transactional(propagation = Propagation.SUPPORTS)
public void bar() {
throw new RuntimeException();
}
}
如果 none 还存在(需要传播),则调用 a.foo()
将启动事务。然后 b.bar() 将被调用并抛出异常。异常被 a.foo()
捕获,它继续执行,就好像什么也没发生一样。 a.foo()
结束时,事务将提交成功。
现在让我们取消注释 b.bar()
上的事务注释。如果 none 存在(需要传播),则调用 a.foo()
将启动事务。然后 b.bar() 将被调用并抛出异常。这个异常将被 B 周围的事务代理"intercepted",它将事务标记为 rollbackOnly。然后异常将传播到 A.a.foo()
。异常被 a.foo()
捕获,它继续执行,就好像什么也没发生一样。在 a.foo()
结束时,事务将被提交,但该提交将失败,因为事务已被标记为 rollbackOnly。 a.foo() 的调用者将得到一个 TransactionSystemException。
Spring 支持两种类型的事务管理 programmatic 和 declarative.
程序化事务管理:这种方式的事务需要由我们来处理。例如-
EntityTransaction tran = entityManager.getTransaction();
try {
tran.begin();
methodWithoutTransactional();
tran.commit();
} catch(Exception ex) {
tran.rollback();
throw ex;
}
声明式事务管理: 以这种方式,我们可以将事务管理代码从我们的业务逻辑中分离出来,只需使用注释或基于 xml 的配置。您已经在示例代码中完成了这些操作-
@Transactional
public void methodWithTransaction1(){
methodWithSupportsTransaction();
}
对于@Transactional注解,如果我们不定义传播类型,默认会应用PROPAGATION_REQUIRED。您可以找到文档 here.