spring学习8-事务控制总结

默认那种异常会回滚事务:默认只有运行时异常会回滚事务,可以配置rollbackfor来指定回滚异常类型。

一、基于配置文件配置事务控制

1.1配置事务管理器

在容器中配置事务管理器,mybatis和jdbc对应的事务管理器是DataSourceTransactionManager

1.2配置事务属性

利用<tx:advice>标签配置事务的属性,包括回滚异常,事务的传播行为等

<tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <tx:method name="find*" read-only="true"/>
            <!--指定事务的隔离级别,配置默认值是使用数据库的配置-->
            <tx:method name="*" isolation="DEFAULT" rollback-for="Exception"/>
        </tx:attributes>
    </tx:advice>

1.3利用aop配置事务作用的方法

利用aop配置切入点

    <aop:config>
        <!--切点表达式要写详细,不能包含事务管理器等类,否则会报循环依赖-->
        <aop:advisor advice-ref="txAdvice" pointcut="execution(public * com.lyy.service.*.*(..))"/>
    </aop:config>

二、基于注解配置事务控制

2.1在配置类上开启注解事务支持

@EnableTransactionManagement

2.2配置事务管理器

利用@Bean注解给容器中加入事务管理器

2.3利用@Transactional注解指定哪个方法需要控制事务

三、xml+注解配置

将事物管理器配置在spring配置文件中,但还希望用@Transactional注解来指定事务方法

需要在配置文件中开启spring对注解事务的支持

<tx:annotation-driven/>

四、编程式手动控制事务

在需要手动控制事务的类中注入事务管理器,利用事务管理器的方法来手动控制事务

@Autowired
    private PlatformTransactionManager transactionManager;

    public void testTransaction() throws Exception {
        TransactionDefinition definition=new DefaultTransactionDefinition();
        TransactionStatus transactionStatus = transactionManager.getTransaction(definition);
        try {
            User user=new User();
            user.setId("1");
            user.setAge(10);
            userMapper.updateById(user);
            int i=1;
            if(i>0){
                throw new Exception("受检异常");
            }
            user.setAge(20);
            userMapper.updateById(user);
            transactionManager.commit(transactionStatus);
        } catch (Exception e) {
            transactionManager.rollback(transactionStatus);
        }
        System.out.println("测试完成");
    }

五、事务的传播行为

解决当一个事务方法被另一个事务方法调用时事务如何处理的问题。

有两个方法A,B,假设B的事务传播行为设置为以下几种(传播行为是设置在被调用的方法上的)

5.1 PROPAGATION_REQUIRED

如果存在一个事务,则支持当前事务。如果没有事务则开启一个新的事务。

方法A调用方法B,如果A有事务,则B加入这个事务中运行,这时如果B抛出了异常,而A捕获了异常,就会发生

Transaction rolled back异常,因为B方法标记事务要回滚,而A方法标记事务要提交,产生了矛盾。

5.2 PROPAGATION_SUPPORTS

如果A存在一个事务,则B支持当前事务,如果A没有事务则B以非事务的模式运行。

5.3 PROPAGATION_MANDATORY

必要的,如果A存在事务,B加入当前事务,如果A没有事务,就会抛出异常

5.4 PROPAGATION_REQUIRES_NEW

新建,如果A存在事务,则先挂起,然后新建事务给B,A和B是两个独立的事务

5.5 PROPAGATION_NESTED

嵌套事务,如果A存在事务,则B以嵌套事务运行,如果A发生异常会回滚B,但如果B发生异常,且在A中捕获了异常,并不会回滚,也不会抛出Transaction rolled back异常

如果A没有事务,则B会新建一个事务

外层抛异常,会不会引起内层回滚: 会,外层抛异常不处理,会引起外层和内层回滚

内层抛异常不处理,会不会回滚外层: 会,内层和外层都会回滚,但如果A捕获了异常,A不会回滚

5.6 PROPAGATION_NOT_SUPPORTED

如果A有事务,则把A的事务挂起,B以非事务运行。

5.7 PROPAGATION_NEVER

从不。如果A有事务,就会抛出异常

5.8 Transaction rolled back异常的出现原因

如果A跟B用的是同一个事务(嵌套事务也算不是同一个事务),B抛出异常,标记事务状态为回滚,但在A中捕获了异常,这时A中会标记事务装填为提交,就会产生此异常。