spring(二)-事务创建及事务的传播机制

一、创建事务

1、配置事务管理器
		<!--    配置数据源  dbcp2  -->
        <bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource">
            <property name="driverClassName" value="${db.driver}"></property>
            <property name="url" value="${db.url}"></property>
            <property name="username" value="${db.username}"></property>
            <property name="password" value="${db.password}"></property>
        </bean>

        <!--   配置事务管理器     -->
        <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <property name="dataSource" ref="dataSource"></property>
        </bean>
        <!--   配置事务支持类     -->
        <tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>

2、使用注解
2.1、注解类

注解类表示在该类中的所有方法都开启事务

@Transactional(propagation = Propagation.REQUIRED)
@Service("addUserImpl1")
public class AddUserImpl1 implements IUser1 {

    @Override
    public void addUser1() {
        User user=new User();
        user.setSn("aa");
        user.setCn("bb");
        user.setSex(null);
        personMapper.insert(user);

    }
}
2.2、注解方法

注解方法表示指定该方法开启事务

@Service("addUserImpl1")
public class AddUserImpl1 implements IUser1 {
	
	@Transactional(propagation = Propagation.REQUIRED)
    @Override
    public void addUser1() {
        User user=new User();
        user.setSn("aa");
        user.setCn("bb");
        user.setSex(null);
        personMapper.insert(user);

    }
}

二、事务的传播机制

1、PROPAGATION.REQUIRED (默认)

支持当前事务,如果当前没有事务,则新建事务
如果当前存在事务(外层方法存在事务),则加入当前事务,合并成一个事务
如果上下文中已经存在事务,那么就加入到事务中执行,如果当前上下文中不存在事务,则新建事务执行。所以这个级别通常能满足处理大多数的业务场景

外层事务:@Transactional(propagation = Propagation.*)或没有事务
内层事务:@Transactional(propagation = Propagation.REQUIRED)
外层事务调用内层事务

如果外层有事务(当前事务),则内层事务加入到外层事务,一块提交,一块回滚(如果内层出现异常且不捕获,此时外层不能捕获该异常,因为 rollback-only = true 必须进行回滚,所以内外层一起回滚(此情况可改为 SUPPORT );如果内层事务捕获异常,则内外层事务不用回滚)。如果外层没有事务,新建一个事务执行(此时只有内层有事务,内外层互不影响;内层或外层无论谁出现异常且没有被捕获都不会影响到对方)

2、Propagation.REQUIRES_NEW

新建事务,如果当前存在事务,则把当前事务挂起
这个方法会独立提交事务,不受调用者的事务影响,父级异常,它也是正常提交

外层事务:@Transactional(propagation = Propagation.*)或没有事务
内层事务:@Transactional(propagation = Propagation.REQUIRES_NEW)
外层事务调用内层事务

无论外层是否有事务,都会在内层中创建一个事务。当内层事务出现异常且没有捕获该异常时,内层事务回滚,如果外层没有对内层抛出的异常进行捕获,则外层(有事务)就回滚;反之不回滚;当内层事务出现异常并捕获该异常时,则内外层都不用进行回滚
总结:内外层相互独立,如果某一层中出现异常但没有捕获异常,则该层进行回滚;如果都没有异常或已捕获异常则正常提交

3、Propagation.NESTED

如果当前存在事务,它将会成为外层事务的一个子事务,方法结束后并没有提交,只有等外层事务结束才提交
如果外层没有事务,则新建事务
如果它异常,父级可以捕获它的异常而不进行回滚,正常提交
但如果外层异常,内层必然回滚(外层有事务的情况下),这就是和 REQUIRES_NEW 的区别
是否回滚由外层事务决定,外层事务不出现异常或捕获异常则内外层事务都不回滚,否则内外层一起回滚

4、SUPPORTS

如果当前存在事务,则加入事务
如果当前不存在事务,则以非事务方式运行

5、NOT_SUPPORTED

以非事务方式运行
如果当前存在事务,则把当前事务挂起

6、MANDATORY

如果当前存在事务,则运行在当前事务中
如果当前无事务,则抛出异常,也即父级方法必须有事务

7、NEVER

以非事务方式运行,如果当前存在事务,则抛出异常,即父级方法必须无事务

三、其他参数

1、isolation

在这里插入图片描述
读未提交

读未提交(Read Uncommitted),是最低的隔离级别,所有的事务都可以看到其他未提交的事务的执行结果。只能防止第一类更新丢失,不能解决脏读,可重复读,幻读,所以很少应用于实际项目。(读事务和写事务同时执行,读事务可以访问写事务未提交的数据)

读已提交

读已提交(Read Committed), 在该隔离级别下,一个事务的更新操作结果只有在该事务提交之后,另一个事务才可能读取到同一笔数据更新后的结果。可以防止脏读,但是不能解决可重复读和幻读的问题。(读事务和写事务同时执行,但写事务未提交的数据, 读事务不能访问,可以防止脏读)

可重复读

可重复读(Repeatable Read),MySQL默认的隔离级别。在该隔离级别下,一个事务多次读同一个数据,在这个事务还没结束时,其他事务不能访问该数据(包括了读写),这样就可以在同一个事务内两次读到的数据是一样的。可以防止脏读、不可重复读的问题,不过还是会出现幻读。(读事务和写事务同时执行,读事务未提交, 写事务不能修改该数据,可以防止脏读、不可重复读)

串行化

串行化(Serializable),这是最高的隔离级别。它要求事务序列化执行,事务只能一个接着一个地执行,不能并发执行。在这个级别,可以解决上面提到的所有并发问题,但可能导致大量的超时现象和锁竞争,通常不会用这个隔离级别。

A、脏读:事务A读取了事务B更新的数据,然后B回滚操作,那么A读取到的数据是脏数据

B、不可重复读:事务 A 多次读取同一数据,事务 B
在事务A多次读取的过程中,对数据作了更新并提交,导致事务A多次读取同一数据时,结果不一致。

C、幻读:系统管理员A将数据库中所有学生的成绩从具体分数改为ABCDE等级,但是系统管理员B就在这个时候插入了一条具体分数的记录,当系统管理员A改结束后发现还有一条记录没有改过来,就好像发生了幻觉一样,这就叫幻读。

小结:不可重复读的和幻读很容易混淆,不可重复读侧重于修改,幻读侧重于新增或删除。解决不可重复读的问题只需锁住满足条件的行,解决幻读需要锁表

2、readOnly

是否为只读事务, 默认 false

3、rollbackFor

指定回滚的异常类型,遇到时必须回滚
如:

rollbackFor = {NullPointerException.class,ArrayIndexOutOfBoundsException.class}
4、rollbackForClassName

指定回滚的异常类名,遇到时必须回滚
如:

rollbackForClassName = {"NullPointerException","ArrayIndexOutOfBoundsException"}
5、noRollbackFor

指定不用回滚的异常类型,遇到时不用回滚
如:

noRollbackFor = {NullPointerException.class,ArrayIndexOutOfBoundsException.class}
6、noRollbackForClassName

指定不用回滚的异常类名,遇到时不用回滚
如:

noRollbackForClassName= {"NullPointerException","ArrayIndexOutOfBoundsException"}
7、timeout

事务超时时间

参考文章

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring事务传播机制是指在多个事务方法调用的场景下,如何管理这些事务的提交和回滚。Spring提供了多种事务传播行为,包括: 1. REQUIRED:如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。这是最常用的传播行为。 2. REQUIRES_NEW:每次都创建一个新的事务,如果当前存在事务,则将其挂起。 3. SUPPORTS:如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务方式执行。 4. NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,则将其挂起。 5. MANDATORY:如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。 6. NEVER:以非事务方式执行操作,如果当前存在事务,则抛出异常。 7. NESTED:如果当前存在事务,则在嵌套事务内执行;如果当前没有事务,则创建一个新的事务。嵌套事务是外部事务的一部分,它有自己的保存点和回滚范围。 事务失效的场景包括: 1. 异常未被捕获并处理,导致事务没有正常回滚。 2. 在没有开启事务的情况下调用带有@Transactional注解的方法,导致方法执行时没有开启事务。 3. 在同一个类中的方法互相调用,而没有通过代理对象进行调用,导致事务失效。 4. 在事务方法中使用了try-catch块并捕获了异常,没有主动抛出异常或调用setRollbackOnly方法,导致事务无法回滚。 需要注意的是,事务的失效可能与具体的配置和使用方式有关,详细的分析和排查需要根据具体的代码和配置进行。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值