【Spring Boot】掌握 Spring 事务:隔离级别与传播机制解读与应用

前言 **???本期讲解关于spring 事务传播机制介绍~~~??感兴趣的小伙伴看一看小编主页:-CSDN博客 ?? 你的点赞就是小编不断更新的最大动力****??那么废话不多说直接开整吧~~目录 [???1.事务的隔离级别](### ??1.事务的隔离级别#### ??1.1MySQL事务隔离级别读未提交(READ UNCOMMITTED): 读未提交, 也叫未提交读. 该隔离级别的事务可以看到其他事务中未提交的数据.> 因为其他事务未提交的数据可能会发回滚, 但是该隔离级别却可以读到, 我们把该级别读到的数据称之为脏数据, 这个问题称之为脏读.(就是一个事务还没有写完,另一个事务就在读了)读提交(READ COMMITTED): 读已提交, 也叫提交读. 该隔离级别的事务能读取到已经提交事务的数据> 该隔离级别不会有脏读的问题.但由于在事务的执中可以读取到其他事务提交的结果, 所以在不同时间的相同 SQL 查询可能会得到不同的结果, 这种现象叫做不可重复读> > (大致就是,事务A在写完后,B读了之后,A又再次修改了,那么B再次读之后,就会发现两次的结果不一样)可重复读(REPEATABLE READ): 事务不会读到其他事务对已有数据的修改, 即使其他事务已提交. 也就可以确保同事务多次查询的结果致, 但是其他事务新插的数据, 是可以感知到的. 这也就引发了幻读问题. 可重复读, 是 MySQL 的默认事务隔离级别.> 如此级别的事务正在执时, 另个事务成功的插了某条数据, 但因为它每次查询的结果都是样的, 所以会导致查询不到这条数据, 重复插时失败(因为唯约束的原因). 明明在事务中查询不到这条信息,但就是插不进去, 这个现象叫幻读)[??1.1MySQL事务隔离级别](### ??1.事务的隔离级别#### ??1.1MySQL事务隔离级别读未提交(READ UNCOMMITTED): 读未提交, 也叫未提交读. 该隔离级别的事务可以看到其他事务中未提交的数据.> 因为其他事务未提交的数据可能会发回滚, 但是该隔离级别却可以读到, 我们把该级别读到的数据称之为脏数据, 这个问题称之为脏读.(就是一个事务还没有写完,另一个事务就在读了)读提交(READ COMMITTED): 读已提交, 也叫提交读. 该隔离级别的事务能读取到已经提交事务的数据> 该隔离级别不会有脏读的问题.但由于在事务的执中可以读取到其他事务提交的结果, 所以在不同时间的相同 SQL 查询可能会得到不同的结果, 这种现象叫做不可重复读> > (大致就是,事务A在写完后,B读了之后,A又再次修改了,那么B再次读之后,就会发现两次的结果不一样)可重复读(REPEATABLE READ): 事务不会读到其他事务对已有数据的修改, 即使其他事务已提交. 也就可以确保同事务多次查询的结果致, 但是其他事务新插的数据, 是可以感知到的. 这也就引发了幻读问题. 可重复读, 是 MySQL 的默认事务隔离级别.> 如此级别的事务正在执时, 另个事务成功的插了某条数据, 但因为它每次查询的结果都是样的, 所以会导致查询不到这条数据, 重复插时失败(因为唯约束的原因). 明明在事务中查询不到这条信息,但就是插不进去, 这个现象叫幻读)[??1.2Spring事务隔离级别](### ??1.事务的隔离级别#### ??1.1MySQL事务隔离级别读未提交(READ UNCOMMITTED): 读未提交, 也叫未提交读. 该隔离级别的事务可以看到其他事务中未提交的数据.> 因为其他事务未提交的数据可能会发回滚, 但是该隔离级别却可以读到, 我们把该级别读到的数据称之为脏数据, 这个问题称之为脏读.(就是一个事务还没有写完,另一个事务就在读了)读提交(READ COMMITTED): 读已提交, 也叫提交读. 该隔离级别的事务能读取到已经提交事务的数据> 该隔离级别不会有脏读的问题.但由于在事务的执中可以读取到其他事务提交的结果, 所以在不同时间的相同 SQL 查询可能会得到不同的结果, 这种现象叫做不可重复读> > (大致就是,事务A在写完后,B读了之后,A又再次修改了,那么B再次读之后,就会发现两次的结果不一样)可重复读(REPEATABLE READ): 事务不会读到其他事务对已有数据的修改, 即使其他事务已提交. 也就可以确保同事务多次查询的结果致, 但是其他事务新插的数据, 是可以感知到的. 这也就引发了幻读问题. 可重复读, 是 MySQL 的默认事务隔离级别.> 如此级别的事务正在执时, 另个事务成功的插了某条数据, 但因为它每次查询的结果都是样的, 所以会导致查询不到这条数据, 重复插时失败(因为唯约束的原因). 明明在事务中查询不到这条信息,但就是插不进去, 这个现象叫幻读)[???2.Spring事务传播机制](### ??1.事务的隔离级别#### ??1.1MySQL事务隔离级别读未提交(READ UNCOMMITTED): 读未提交, 也叫未提交读. 该隔离级别的事务可以看到其他事务中未提交的数据.> 因为其他事务未提交的数据可能会发回滚, 但是该隔离级别却可以读到, 我们把该级别读到的数据称之为脏数据, 这个问题称之为脏读.(就是一个事务还没有写完,另一个事务就在读了)读提交(READ COMMITTED): 读已提交, 也叫提交读. 该隔离级别的事务能读取到已经提交事务的数据> 该隔离级别不会有脏读的问题.但由于在事务的执中可以读取到其他事务提交的结果, 所以在不同时间的相同 SQL 查询可能会得到不同的结果, 这种现象叫做不可重复读> > (大致就是,事务A在写完后,B读了之后,A又再次修改了,那么B再次读之后,就会发现两次的结果不一样)可重复读(REPEATABLE READ): 事务不会读到其他事务对已有数据的修改, 即使其他事务已提交. 也就可以确保同事务多次查询的结果致, 但是其他事务新插的数据, 是可以感知到的. 这也就引发了幻读问题. 可重复读, 是 MySQL 的默认事务隔离级别.> 如此级别的事务正在执时, 另个事务成功的插了某条数据, 但因为它每次查询的结果都是样的, 所以会导致查询不到这条数据, 重复插时失败(因为唯约束的原因). 明明在事务中查询不到这条信息,但就是插不进去, 这个现象叫幻读)[??2.1什么是事务的传播机制](### ??1.事务的隔离级别#### ??1.1MySQL事务隔离级别读未提交(READ UNCOMMITTED): 读未提交, 也叫未提交读. 该隔离级别的事务可以看到其他事务中未提交的数据.> 因为其他事务未提交的数据可能会发回滚, 但是该隔离级别却可以读到, 我们把该级别读到的数据称之为脏数据, 这个问题称之为脏读.(就是一个事务还没有写完,另一个事务就在读了)读提交(READ COMMITTED): 读已提交, 也叫提交读. 该隔离级别的事务能读取到已经提交事务的数据> 该隔离级别不会有脏读的问题.但由于在事务的执中可以读取到其他事务提交的结果, 所以在不同时间的相同 SQL 查询可能会得到不同的结果, 这种现象叫做不可重复读> > (大致就是,事务A在写完后,B读了之后,A又再次修改了,那么B再次读之后,就会发现两次的结果不一样)可重复读(REPEATABLE READ): 事务不会读到其他事务对已有数据的修改, 即使其他事务已提交. 也就可以确保同事务多次查询的结果致, 但是其他事务新插的数据, 是可以感知到的. 这也就引发了幻读问题. 可重复读, 是 MySQL 的默认事务隔离级别.> 如此级别的事务正在执时, 另个事务成功的插了某条数据, 但因为它每次查询的结果都是样的, 所以会导致查询不到这条数据, 重复插时失败(因为唯约束的原因). 明明在事务中查询不到这条信息,但就是插不进去, 这个现象叫幻读)[??2.2事务隔离与传播的区别](### ??1.事务的隔离级别#### ??1.1MySQL事务隔离级别读未提交(READ UNCOMMITTED): 读未提交, 也叫未提交读. 该隔离级别的事务可以看到其他事务中未提交的数据.> 因为其他事务未提交的数据可能会发回滚, 但是该隔离级别却可以读到, 我们把该级别读到的数据称之为脏数据, 这个问题称之为脏读.(就是一个事务还没有写完,另一个事务就在读了)读提交(READ COMMITTED): 读已提交, 也叫提交读. 该隔离级别的事务能读取到已经提交事务的数据> 该隔离级别不会有脏读的问题.但由于在事务的执中可以读取到其他事务提交的结果, 所以在不同时间的相同 SQL 查询可能会得到不同的结果, 这种现象叫做不可重复读> > (大致就是,事务A在写完后,B读了之后,A又再次修改了,那么B再次读之后,就会发现两次的结果不一样)可重复读(REPEATABLE READ): 事务不会读到其他事务对已有数据的修改, 即使其他事务已提交. 也就可以确保同事务多次查询的结果致, 但是其他事务新插的数据, 是可以感知到的. 这也就引发了幻读问题. 可重复读, 是 MySQL 的默认事务隔离级别.> 如此级别的事务正在执时, 另个事务成功的插了某条数据, 但因为它每次查询的结果都是样的, 所以会导致查询不到这条数据, 重复插时失败(因为唯约束的原因). 明明在事务中查询不到这条信息,但就是插不进去, 这个现象叫幻读)[??2.3事务的传播机制](### ??1.事务的隔离级别#### ??1.1MySQL事务隔离级别读未提交(READ UNCOMMITTED): 读未提交, 也叫未提交读. 该隔离级别的事务可以看到其他事务中未提交的数据.> 因为其他事务未提交的数据可能会发回滚, 但是该隔离级别却可以读到, 我们把该级别读到的数据称之为脏数据, 这个问题称之为脏读.(就是一个事务还没有写完,另一个事务就在读了)读提交(READ COMMITTED): 读已提交, 也叫提交读. 该隔离级别的事务能读取到已经提交事务的数据> 该隔离级别不会有脏读的问题.但由于在事务的执中可以读取到其他事务提交的结果, 所以在不同时间的相同 SQL 查询可能会得到不同的结果, 这种现象叫做不可重复读> > (大致就是,事务A在写完后,B读了之后,A又再次修改了,那么B再次读之后,就会发现两次的结果不一样)可重复读(REPEATABLE READ): 事务不会读到其他事务对已有数据的修改, 即使其他事务已提交. 也就可以确保同事务多次查询的结果致, 但是其他事务新插的数据, 是可以感知到的. 这也就引发了幻读问题. 可重复读, 是 MySQL 的默认事务隔离级别.> 如此级别的事务正在执时, 另个事务成功的插了某条数据, 但因为它每次查询的结果都是样的, 所以会导致查询不到这条数据, 重复插时失败(因为唯约束的原因). 明明在事务中查询不到这条信息,但就是插不进去, 这个现象叫幻读)[??2.4事务传播机制代码演示](### ??1.事务的隔离级别#### ??1.1MySQL事务隔离级别读未提交(READ UNCOMMITTED): 读未提交, 也叫未提交读. 该隔离级别的事务可以看到其他事务中未提交的数据.> 因为其他事务未提交的数据可能会发回滚, 但是该隔离级别却可以读到, 我们把该级别读到的数据称之为脏数据, 这个问题称之为脏读.(就是一个事务还没有写完,另一个事务就在读了)读提交(READ COMMITTED): 读已提交, 也叫提交读. 该隔离级别的事务能读取到已经提交事务的数据> 该隔离级别不会有脏读的问题.但由于在事务的执中可以读取到其他事务提交的结果, 所以在不同时间的相同 SQL 查询可能会得到不同的结果, 这种现象叫做不可重复读> > (大致就是,事务A在写完后,B读了之后,A又再次修改了,那么B再次读之后,就会发现两次的结果不一样)可重复读(REPEATABLE READ): 事务不会读到其他事务对已有数据的修改, 即使其他事务已提交. 也就可以确保同事务多次查询的结果致, 但是其他事务新插的数据, 是可以感知到的. 这也就引发了幻读问题. 可重复读, 是 MySQL 的默认事务隔离级别.> 如此级别的事务正在执时, 另个事务成功的插了某条数据, 但因为它每次查询的结果都是样的, 所以会导致查询不到这条数据, 重复插时失败(因为唯约束的原因). 明明在事务中查询不到这条信息,但就是插不进去, 这个现象叫幻读)[2.4.1REQUIRED](### ??1.事务的隔离级别#### ??1.1MySQL事务隔离级别读未提交(READ UNCOMMITTED): 读未提交, 也叫未提交读. 该隔离级别的事务可以看到其他事务中未提交的数据.> 因为其他事务未提交的数据可能会发回滚, 但是该隔离级别却可以读到, 我们把该级别读到的数据称之为脏数据, 这个问题称之为脏读.(就是一个事务还没有写完,另一个事务就在读了)读提交(READ COMMITTED): 读已提交, 也叫提交读. 该隔离级别的事务能读取到已经提交事务的数据> 该隔离级别不会有脏读的问题.但由于在事务的执中可以读取到其他事务提交的结果, 所以在不同时间的相同 SQL 查询可能会得到不同的结果, 这种现象叫做不可重复读> > (大致就是,事务A在写完后,B读了之后,A又再次修改了,那么B再次读之后,就会发现两次的结果不一样)可重复读(REPEATABLE READ): 事务不会读到其他事务对已有数据的修改, 即使其他事务已提交. 也就可以确保同事务多次查询的结果致, 但是其他事务新插的数据, 是可以感知到的. 这也就引发了幻读问题. 可重复读, 是 MySQL 的默认事务隔离级别.> 如此级别的事务正在执时, 另个事务成功的插了某条数据, 但因为它每次查询的结果都是样的, 所以会导致查询不到这条数据, 重复插时失败(因为唯约束的原因). 明明在事务中查询不到这条信息,但就是插不进去, 这个现象叫幻读)[?2.4.2REQUIRES_NEW](### ??1.事务的隔离级别#### ??1.1MySQL事务隔离级别读未提交(READ UNCOMMITTED): 读未提交, 也叫未提交读. 该隔离级别的事务可以看到其他事务中未提交的数据.> 因为其他事务未提交的数据可能会发回滚, 但是该隔离级别却可以读到, 我们把该级别读到的数据称之为脏数据, 这个问题称之为脏读.(就是一个事务还没有写完,另一个事务就在读了)读提交(READ COMMITTED): 读已提交, 也叫提交读. 该隔离级别的事务能读取到已经提交事务的数据> 该隔离级别不会有脏读的问题.但由于在事务的执中可以读取到其他事务提交的结果, 所以在不同时间的相同 SQL 查询可能会得到不同的结果, 这种现象叫做不可重复读> > (大致就是,事务A在写完后,B读了之后,A又再次修改了,那么B再次读之后,就会发现两次的结果不一样)可重复读(REPEATABLE READ): 事务不会读到其他事务对已有数据的修改, 即使其他事务已提交. 也就可以确保同事务多次查询的结果致, 但是其他事务新插的数据, 是可以感知到的. 这也就引发了幻读问题. 可重复读, 是 MySQL 的默认事务隔离级别.> 如此级别的事务正在执时, 另个事务成功的插了某条数据, 但因为它每次查询的结果都是样的, 所以会导致查询不到这条数据, 重复插时失败(因为唯约束的原因). 明明在事务中查询不到这条信息,但就是插不进去, 这个现象叫幻读)[2.4.3NEVER](### ??1.事务的隔离级别#### ??1.1MySQL事务隔离级别读未提交(READ UNCOMMITTED): 读未提交, 也叫未提交读. 该隔离级别的事务可以看到其他事务中未提交的数据.> 因为其他事务未提交的数据可能会发回滚, 但是该隔离级别却可以读到, 我们把该级别读到的数据称之为脏数据, 这个问题称之为脏读.(就是一个事务还没有写完,另一个事务就在读了)读提交(READ COMMITTED): 读已提交, 也叫提交读. 该隔离级别的事务能读取到已经提交事务的数据> 该隔离级别不会有脏读的问题.但由于在事务的执中可以读取到其他事务提交的结果, 所以在不同时间的相同 SQL 查询可能会得到不同的结果, 这种现象叫做不可重复读> > (大致就是,事务A在写完后,B读了之后,A又再次修改了,那么B再次读之后,就会发现两次的结果不一样)可重复读(REPEATABLE READ): 事务不会读到其他事务对已有数据的修改, 即使其他事务已提交. 也就可以确保同事务多次查询的结果致, 但是其他事务新插的数据, 是可以感知到的. 这也就引发了幻读问题. 可重复读, 是 MySQL 的默认事务隔离级别.> 如此级别的事务正在执时, 另个事务成功的插了某条数据, 但因为它每次查询的结果都是样的, 所以会导致查询不到这条数据, 重复插时失败(因为唯约束的原因). 明明在事务中查询不到这条信息,但就是插不进去, 这个现象叫幻读)[2.4.4NESTED](### ??1.事务的隔离级别#### ??1.1MySQL事务隔离级别读未提交(READ UNCOMMITTED): 读未提交, 也叫未提交读. 该隔离级别的事务可以看到其他事务中未提交的数据.> 因为其他事务未提交的数据可能会发回滚, 但是该隔离级别却可以读到, 我们把该级别读到的数据称之为脏数据, 这个问题称之为脏读.(就是一个事务还没有写完,另一个事务就在读了)读提交(READ COMMITTED): 读已提交, 也叫提交读. 该隔离级别的事务能读取到已经提交事务的数据> 该隔离级别不会有脏读的问题.但由于在事务的执中可以读取到其他事务提交的结果, 所以在不同时间的相同 SQL 查询可能会得到不同的结果, 这种现象叫做不可重复读> > (大致就是,事务A在写完后,B读了之后,A又再次修改了,那么B再次读之后,就会发现两次的结果不一样)可重复读(REPEATABLE READ): 事务不会读到其他事务对已有数据的修改, 即使其他事务已提交. 也就可以确保同事务多次查询的结果致, 但是其他事务新插的数据, 是可以感知到的. 这也就引发了幻读问题. 可重复读, 是 MySQL 的默认事务隔离级别.> 如此级别的事务正在执时, 另个事务成功的插了某条数据, 但因为它每次查询的结果都是样的, 所以会导致查询不到这条数据, 重复插时失败(因为唯约束的原因). 明明在事务中查询不到这条信息,但就是插不进去, 这个现象叫幻读)[??2.5NESTED和REQUIRED 区别](### ??1.事务的隔离级别#### ??1.1MySQL事务隔离级别读未提交(READ UNCOMMITTED): 读未提交, 也叫未提交读. 该隔离级别的事务可以看到其他事务中未提交的数据.> 因为其他事务未提交的数据可能会发回滚, 但是该隔离级别却可以读到, 我们把该级别读到的数据称之为脏数据, 这个问题称之为脏读.(就是一个事务还没有写完,另一个事务就在读了)读提交(READ COMMITTED): 读已提交, 也叫提交读. 该隔离级别的事务能读取到已经提交事务的数据> 该隔离级别不会有脏读的问题.但由于在事务的执中可以读取到其他事务提交的结果, 所以在不同时间的相同 SQL 查询可能会得到不同的结果, 这种现象叫做不可重复读> > (大致就是,事务A在写完后,B读了之后,A又再次修改了,那么B再次读之后,就会发现两次的结果不一样)可重复读(REPEATABLE READ): 事务不会读到其他事务对已有数据的修改, 即使其他事务已提交. 也就可以确保同事务多次查询的结果致, 但是其他事务新插的数据, 是可以感知到的. 这也就引发了幻读问题. 可重复读, 是 MySQL 的默认事务隔离级别.> 如此级别的事务正在执时, 另个事务成功的插了某条数据, 但因为它每次查询的结果都是样的, 所以会导致查询不到这条数据, 重复插时失败(因为唯约束的原因). 明明在事务中查询不到这条信息,但就是插不进去, 这个现象叫幻读)[???3.总结](### ??1.事务的隔离级别#### ??1.1MySQL事务隔离级别读未提交(READ UNCOMMITTED): 读未提交, 也叫未提交读. 该隔离级别的事务可以看到其他事务中未提交的数据.> 因为其他事务未提交的数据可能会发回滚, 但是该隔离级别却可以读到, 我们把该级别读到的数据称之为脏数据, 这个问题称之为脏读.(就是一个事务还没有写完,另一个事务就在读了)读提交(READ COMMITTED): 读已提交, 也叫提交读. 该隔离级别的事务能读取到已经提交事务的数据> 该隔离级别不会有脏读的问题.但由于在事务的执中可以读取到其他事务提交的结果, 所以在不同时间的相同 SQL 查询可能会得到不同的结果, 这种现象叫做不可重复读> > (大致就是,事务A在写完后,B读了之后,A又再次修改了,那么B再次读之后,就会发现两次的结果不一样)可重复读(REPEATABLE READ): 事务不会读到其他事务对已有数据的修改, 即使其他事务已提交. 也就可以确保同事务多次查询的结果致, 但是其他事务新插的数据, 是可以感知到的. 这也就引发了幻读问题. 可重复读, 是 MySQL 的默认事务隔离级别.> 如此级别的事务正在执时, 另个事务成功的插了某条数据, 但因为它每次查询的结果都是样的, 所以会导致查询不到这条数据, 重复插时失败(因为唯约束的原因). 明明在事务中查询不到这条信息,但就是插不进去, 这个现象叫幻读)### ??1.事务的隔离级别#### ??1.1MySQL事务隔离级别读未提交(READ UNCOMMITTED): 读未提交, 也叫未提交读. 该隔离级别的事务可以看到其他事务中未提交的数据.> 因为其他事务未提交的数据可能会发回滚, 但是该隔离级别却可以读到, 我们把该级别读到的数据称之为脏数据, 这个问题称之为脏读.(就是一个事务还没有写完,另一个事务就在读了)读提交(READ COMMITTED) : 读已提交, 也叫提交读. 该隔离级别的事务能读取到已经提交事务的数据> 该隔离级别不会有脏读的问题.但由于在事务的执中可以读取到其他事务提交的结果, 所以在不同时间的相同 SQL 查询可能会得到不同的结果, 这种现象叫做不可重复读> > (大致就是,事务A在写完后,B读了之后,A又再次修改了,那么B再次读之后,就会发现两次的结果不一样)可重复读(REPEATABLE READ): 事务不会读到其他事务对已有数据的修改, 即使其他事务已提交. 也就可以确保同事务多次查询的结果致, 但是其他事务新插的数据, 是可以感知到的. 这也就引发了幻读问题. 可重复读, 是 MySQL 的默认事务隔离级别.> 如此级别的事务正在执时, 另个事务成功的插了某条数据, 但因为它每次查询的结果都是样的, 所以会导致查询不到这条数据, 重复插时失败(因为唯约束的原因). 明明在事务中查询不到这条信息,但就是插不进去, 这个现象叫幻读 串化(SERIALIZABLE)😗* 序列化, 事务最隔离级别. 它会强制事务排序, 使之不会发冲突, 从解决了脏读, 不可重复读和幻读问题, 但因为执效率低, 所以真正使的场景并不多#### ??1.2Spring事务隔离级别Spring 中事务隔离级别有5 种:1. Isolation.DEFAULT : 以连接的数据库的事务隔离级别为主. 2. Isolation.READ_UNCOMMITTED : 读未提交, 对应SQL标准中 READ UNCOMMITTED 3. Isolation.READ_COMMITTED : 读已提交,对应SQL标准中 READ COMMITTED 4. Isolation.REPEATABLE_READ : 可重复读, 对应SQL标准中 REPEATABLE READ 5. Isolation.SERIALIZABLE : 串化, 对应SQL标准中 SERIALIZABLE设置事务的隔离级别代码如下: @Transactional(rollbackFor = Exception.class, isolation = Isolation.DEFAULT) //设置所有回滚异常类型 @RequestMapping("/r7") public Boolean r7(String userName, String password) throws IOException { Integer result = userService.registUser(userName, password); System.out.println("插入用户表, result: "+ result); if (true){ throw new IOException(); } return true; }解释:在代码中,注解里的参数rollbackfor指定所有异常都需要进行回滚,然后isolation指定是与数据库的事务隔离级别是一致的,那么这里的spring事务的隔离级别就是可重复读;### ??2.Spring事务传播机制#### ??2.1什么是事务的传播机制> 事务传播机制就是: 多个事务法存在调关系时, 事务是如何在这些法间进传播的就比如,两个方法,都被transaction修饰了,假如这里的两个方法存在调用的关系,那么这里的事务是如何进行传播的,是使用A的事务,还是使用B的事务呢?#### ??2.2事务隔离与传播的区别事务隔离级别解决的是多个事务同时调个数据库的问题如下图:事务传播机制解决的是个事务在多个节点(法)中传递的问题#### ??2.3事务的传播机制@Transactional 注解持事务传播机制的设置, 通过 propagation 属性来指定传播为. Spring 事务传播机制有以下 7 种:B是被调用的一方(service),A是调用的一方(controller)1. Propagation.REQUIRED : 默认的事务传播级别. 如果当前存在事务, 则加该事务. 如果当前没 有事务, 则创建个新的事务.)> A有事务,B就直接使用A的事务,如果A没有事务,B创建一个事务2. Propagation.SUPPORTS : 如果当前存在事务, 则加该事务. 如果当前没有事务, 则以事务的式继续运.> A有事务,B就直接使用A的事务,如果A没有事务,B以非事务的方式进行运行 3. Propagation.MANDATORY :强制性. 如果当前存在事务, 则加该事务. 如果当前没有事务, 则 抛出异常.> A有事务,B就直接使用A的事务,如果A没有事务,那么就直接抛出异常4. Propagation.REQUIRES_NEW : 创建个新的事务. 如果当前存在事务, 则把当前事务挂起. 也 就是说不管外部法是否开启事务, Propagation.REQUIRES_NEW 修饰的内部法都会新开 启的事务, 且开启的事务相互独, 互不扰.> 就是不管A有无事务,B都创建新的事务5. Propagation.NOT_SUPPORTED : 以事务式运, 如果当前存在事务, 则把当前事务挂起(不).> 就是不管A有无事务,B都直接以非事务的方式进行运行6. Propagation.NEVER : 以事务式运, 如果当前存在事务, 则抛出异常> 如果A事务存在,那么就直接抛出异常7. Propagation.NESTED : 如果当前存在事务, 则创建个事务作为当前事务的嵌套事务来运. 如果当前没有事务, 则该取值等价于 PROPAGATION_REQUIRED> 没有事务就创建事务,有的话就干点其他的事情#### ??2.4事务传播机制代码演示##### 2.4.1REQUIRED****controller控制层,代表的A @RequestMapping("/user") @RestController public class UserController2 { @Autowired private UserService userService; @Autowired private LogService logService; @Transactional(propagation = Propagation.REQUIRED) @RequestMapping("/p1") public String r3(String name, String password) { //??注册 userService.registUser(name, password); //记录操作?志 logService.insertLog(name, "??注册"); return "p1"; } } 其余两个service:登录日志打印: @Service public class LogService { @Autowired private LogInfoMapper logInfoMapper; @Transactional(propagation = Propagation.REQUIRED) public void insertLog(String userName,String op){ logInfoMapper.insert(userName,"用户注册"); int a=10/0; } } user登录: @Service public class UserService { @Autowired private UserInfoMapper userInfoMapper; @Transactional(propagation = Propagation.REQUIRED) public Integer registUser(String userName, String password) { Integer result = userInfoMapper.insert(userName, password); return result; } } 输出情况,打印的日志如下:1. p1 法开始事务 2. 注册, 插条数据 (执成功) (和p1 使同个事务) 3. 记录操作志, 插条数据(出现异常, 执失败) (和p1 使同个事务) 4. 因为步骤3出现异常, 事务回滚. 步骤2和3使同个事务, 所以步骤2的数据也回滚了.##### 2.4.2REQUIRES_NEW 我们将这里的两个service层改成REQUIRES_NEW 这里的其中一个事务进行了提交;另一个代码存在算数异常的就没有进行提交这里就是单独创建了自己的事务,这里的两个service层创建的两个事务就不会相互影响,所以其中一个提交,另一个进行了回滚的操作;##### 2.4.3NEVER 我们将其中一个代码传播机制改变 @Service public class UserService { @Autowired private UserInfoMapper userInfoMapper; @Transactional(propagation = Propagation.NEVER) public Integer registUser(String userName, String password) { Integer result = userInfoMapper.insert(userName, password); return result; } }输出的日志如下所示:那么这里可以看到报错信息就是A调用层存在事务,导致报错;##### 2.4.4NESTED 将上述UserService 和LogService 中相关法事务传播机制改为 Propagation.NESTED小编这里就不演示代码了,大家可以自己去试一试;打印日志如下:由于是嵌套事务, LogService 出现异常之后, 往上找调它的法和事务, 所以注册也失败 了.最终结果是两个数据都没有添加 p1事务可以认为是事务, 嵌套事务是事务. 事务出现异常, 事务也会回滚, 事务出现异常, 如果不进处理, 也会导致事务回滚(可以认为是REQUIRED,但是不完全是 )#### ??2.5NESTED和REQUIRED 区别我们知道,当两个方法不存在问题时,这里的两种传播机制是没有啥区别的,但是当出现问题时,我们可以发现情况如上图所示,但是真的没有区别吗?答案是否定的; @Service public class LogService { @Autowired private LogInfoMapper logInfoMapper; @Transactional(propagation = Propagation.NESTED) public void insertLog(String userName,String op){ try { int a=10/0; }catch (Exception e){ TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); } logInfoMapper.insert(userName,"用户注册"); } }重新运程序, 发现表数据添加成功, 志表添加失败. LogService 中的事务已经回滚, 但是嵌套事务不会回滚嵌套之前的事务, 也就是说嵌套事务可以实 现部分事务回滚但是对于REQUIRED 如果回滚就是回滚所有事务, 不能实现部分事务的回滚. (因为属于同个事务)> 嵌套事务之所以能够实现部分事务的回滚, 是因为事务中有个保存点(savepoint)的概念, 嵌套事务进之后相当于新建了个保存点, 滚回时只回滚到当前保存点.这里是小编的理解,大家有问题或者质疑可以私信我哟~~~### ??3.总结 ???本期讲解了关于MySQL事务的隔离级别回顾,以及spring的事务隔离级别以及事务传播机制,分别从概念和代码进行了演示~~~???~~~~最后希望与诸君共勉,共同进步!!! * * ???以上就是本期内容了, 感兴趣的话,就关注小编吧。 *???期待你的关注~~~**

相关推荐
gis开发之家32 分钟前
Spring Boot 4 深度解析,JdbcTemplate 实战——轻量级数据库操作方案
java·数据库·spring boot·后端
李昊哲小课1 小时前
Spring Boot 4 旅游主题实战教程 阶段二:Web 开发基础
前端·spring boot·旅游
2601_962063972 小时前
Spring Boot拦截器(Interceptor)详解
java·spring boot·后端
不才不才不不才2 小时前
Spring 源码系列(25): @EnableTransactionManagement 与 TransactionInterceptor
java·数据库·spring
李昊哲小课2 小时前
SpringBoot4 云端咖啡站 阶段一:起步与基础
spring boot
MetaLite2 小时前
Spring-Scheduled多实例重复执行怎么办-Redis分布式锁如何只让一个节点运行
redis·分布式·spring
wangchunyu1143 小时前
Elasticsearch 入门与实战:Spring Boot 3 + ES 8 从零搭建商品搜索服务
大数据·数据库·spring boot·elasticsearch
catino4 小时前
spring-IOC、DI
java·spring·rpc
xcl09254 小时前
从零开发流浪宠物领养平台:技术选型与核心模块设计
java·spring boot·宠物