Spring中的事务以及事务传播级别

news/2025/1/16 3:44:45/

一、Spring中事务的隔离级别

Spring 提供了 5 种不同的事务隔离级别,每种级别都代表了一种不同的隔离程度:

1.Isolation.DEFAULT:默认级别,使用数据库默认的隔离级别。不同的数据库默认隔离级别可能不同。

2.Isolation.READ_UNCOMMITTED:最低的隔离级别,事务可以读取未提交的数据,也就是脏读(Dirty Read)。

3.Isolation.READ_COMMITTED:事务只能读取已经提交的数据,可以避免脏读,但是可能会出现不可重复读(Non-repeatable Read)。

4.**Isolation.REPEATABLE_READ:**事务可以多次读取同一数据,保证了数据一致性,但是可能会出现幻读(Phantom Read)。

5.**Isolation.SERIALIZABLE:**最高的隔离级别,事务串行执行,避免了脏读、不可重复读和幻读,但是性能较差。

不可重复度:针对的是数据的修改,前后两次读到的数据不一样。
幻读:针对数据的添加和删除,前后读到的数据数量的不同。

二、七种传播级别

事务的传播级别(Propagation Level)是指在多个事务方法相互调用时,事务如何传播的规则。Spring 提供了 7 种不同的传播级别,每种级别都代表了一种不同的事务传播行为:

1、Propagation.REQUIRED:默认值。如果当前存在事务,则加入该事务;如果不存在事务,则创建一个新的事务。

2、Propagation.SUPPORTS:如果当前存在事务,则加入该事务;如果不存在事务,则不会创建一个新的事务。
3、Propagation.MANDATORY:如果当前存在事务,则加入该事务;如果不存在事务,则抛出一个异常。
4、Propagation.REQUIRES_NEW:无论当前是否存在事务,都会创建一个新的事务。如果当前存在事务,则挂起当前事务,执行新的事务,新的事务执行完毕后再恢复当前事务。
5、Propagation.NOT_SUPPORTED:如果当前存在事务,则挂起当前事务,以非事务状态执行该方法;执行完毕后再恢复当前事务。
6、Propagation.NEVER:如果当前存在事务,则抛出一个异常;如果不存在事务,则以非事务状态执行该方法。
7、Propagation.NESTED:如果当前存在事务,则在当前事务中嵌套一个新的事务;如果不存在事务,则创建一个新的事务。嵌套的事务可以独立提交或回滚,但是如果外层事务回滚,则内层事务也会回滚。

三、七种传播级别的举例

1、Propagation.REQUIRED:

@Transactional
public void methodA(){// do somethingmethodB();// do something
}@Transactional
public void methodB(){// do something
}

在这个例子中,方法 A 和方法 B 都使用了默认的传播级别 Propagation.REQUIRED,即如果当前存在事务,则加入该事务;如果不存在事务,则创建一个新的事务。当调用 methodB() 时,methodB() 将会加入 methodA() 的事务中,因为 methodA() 已经开启了一个事务。当 methodB() 结束时,methodA() 的事务也将结束。如果 methodB() 抛出了异常,则 methodA() 也将回滚。
2、Propagation.SUPPORTS:

@Transactional
public void methodA(){// do somethingmethodB();// do something
}@Transactional(propagation = Propagation.SUPPORTS)
public void methodB(){// do something
}

在这个例子中,方法 A 使用了默认的传播级别 Propagation.REQUIRED,而方法 B 使用了传播级别 Propagation.SUPPORTS,即如果当前存在事务,则加入该事务;如果不存在事务,则不会创建一个新的事务。当调用 methodB() 时,它将加入 methodA() 的事务中,因为 methodA() 已经开启了一个事务。如果 methodB() 抛出了异常,则 methodA() 也将回滚。

3、Propagation.MANDATORY:

@Transactional
public void methodA(){// do somethingmethodB();// do something
}@Transactional(propagation = Propagation.MANDATORY)
public void methodB(){// do something
}

在这个例子中,方法 A 使用了默认的传播级别 Propagation.REQUIRED,而方法 B 使用了传播级别 Propagation.MANDATORY,即如果当前存在事务,则加入该事务;如果不存在事务,则抛出一个异常。当调用 methodB() 时,它将加入 methodA() 的事务中,因为 methodA() 已经开启了一个事务。如果 methodA() 没有事务,则 methodB() 将抛出一个异常。

4、Propagation.REQUIRES_NEW:

@Transactional

public void methodA(){// do somethingmethodB();// do something
}@Transactional(propagation = Propagation.REQUIRES_NEW)
public void methodB(){// do something
}

在这个例子中,方法 A 使用了默认的传播级别 Propagation.REQUIRED,而方法 B 使用了传播级别 Propagation.REQUIRES_NEW,即无论当前是否存在事务,都会创建一个新的事务。当调用 methodB() 时,它将在一个新的事务中执行,与 methodA() 的事务无关。当 methodB() 结束时,仅仅会提交 methodB() 的事务,而不会影响 methodA() 的事务。

5、Propagation.NOT_SUPPORTED:

@Transactional
public void methodA(){// do somethingmethodB();// do something
}@Transactional(propagation = Propagation.NOT_SUPPORTED)
public void methodB(){// do something
}

在这个例子中,方法 A 使用了默认的传播级别 Propagation.REQUIRED,而方法 B 使用了传播级别 Propagation.NOT_SUPPORTED,即如果当前存在事务,则挂起当前事务,以非事务状态执行该方法;执行完毕后再恢复当前事务。当调用 methodB() 时,它将挂起 methodA() 的事务,以非事务状态执行 methodB(),当 methodB() 结束时,恢复 methodA() 的事务。

6、Propagation.NEVER:

@Transactional
public void methodA(){// do somethingmethodB();// do something
}@Transactional(propagation = Propagation.NEVER)
public void methodB(){// do something
}

在这个例子中,方法 A 使用了默认的传播级别 Propagation.REQUIRED,而方法 B 使用了传播级别 Propagation.NEVER,即如果当前存在事务,则抛出一个异常;如果不存在事务,则以非事务状态执行该方法。当调用 methodB() 时,如果 methodA() 已经开启了一个事务,则 methodB() 将抛出一个异常;如果 methodA() 没有事务,则 methodB() 将在非事务状态下执行。

7、Propagation.NESTED:

@Transactional
public void methodA(){// do somethingmethodB();// do something
}@Transactional(propagation = Propagation.NESTED)
public void methodB(){// do something
}

在这个例子中,方法 A 使用了默认的传播级别 Propagation.REQUIRED,而方法 B 使用了传播级别 Propagation.NESTED,即如果当前存在事务,则在当前事务中嵌套一个新的事务;如果不存在事务,则创建一个新的事务。当调用 methodB() 时,它将在 methodA() 的事务中嵌套一个新的事务,这个新的事务可以独立提交或回滚,但是如果 methodA() 的事务回滚,则 methodB() 的事务也会回滚。


http://www.ppmy.cn/news/849324.html

相关文章

外置硬盘一插就卡_插上移动硬盘或读卡器或存储卡,电脑就死机(而且看不到盘符),拔掉就又活了…解决方案...

献 插上移动硬盘或读卡器或存储卡,电脑就死机(而 且看不到盘符),拔掉就又活了…解决方案 故障说明:1只要移动硬盘连在电脑上,开机无法完成,一直停在输入密码之 前的欢迎界面.但是如果不插硬盘,就什么事都没有.如果开了机再插移动 硬盘,电脑立刻死机,什么软件都无法运行,同时在我…

mysql硬盘备份_原创-在mysql中把里面的数据库备份到自己的硬盘上

原创-在mysql中把里面的数据库备份到自己的硬盘上 (2011-04-15 20:33:23) 标签: 千百度女鞋 杂谈 在mysql中把内中的数值库备份到本人的硬盘上在数值库表拾失或许破坏的情况下,备份你的数值库是很主要的。假如产生体系瓦解,你确定想能够或者许将你的表绝可能拾失起码…

函数基础

一、初识函数 函数,可以当做是一大堆功能代码的集合。 def 函数名():函数内编写代码......函数名()例如: # 定义名字叫info的函数 def info():print("第一行")print("第二行")print("第n行...")info()运用函数的场景&a…

quartus II :DDR2使用-接口芯片MT47H64M16HR

1、tools-,-interfaces-external mermory-DDR2,写入内核名字。 2、写时钟频率,如果要仿真最后需要勾选产生仿真程序选项 3、添加型号时候可能看不到MT47H64M16HR。需要手动添加内核到目录 4、生成过程中卡死。结束进程 quartus_map &#xff…

notes for IS66WVC4M16EALL-7010BLI

存储器型号: IS66WVC4M16EALL-7010BLI BCR寄存器 输入时钟频率不同,需要设置不同的BCR寄存器的值: 逻辑代码思路 1. 用计数器将地址分段,比如每个通道占据两段或者三段,合起来为一行数据; 2. 用fifo将…

mysql优化 个人笔记 - 非礼勿扰 -m16

一 、 服务器参数设置 vim /etc/my.conf1. 通用设置 #数据文件存放目录 datadir/var/lib/mysql # mysql.socket表示server和client在同一台服务器, # 并且使用localhost进行连接,就会使用socket进行连接 socket/var/lib/mysql/mysql.socket # 存储mys…

mov sreg, r/m16 在16位和32位编程中的区别

总结于《X86汇编语言 从实模式到保护模式》 仅适用于X86系列处理器 1. 两者的区别: 例:mov ds, ax   A.在指定16位编译模式下,产生的二进制码是 8E D8   B.在指定32位编译模式下(在某些老式的编译器中才会出现的),产生的二进…

从quatus内部启动modelsim进行后仿真 出现Instantiation of 'mt48lc32m16a2' failed. The design unit was not found.

问题:当我进行前仿真的时候,quatus编译成功,modelsim流畅运行,非常顺利,功能验证正确!但是当我进行后仿真的时候却一直出现Instantiation of mt48lc32m16a2 failed. The design unit was not found.。我百思…