spring基础事务学习

Spring事务

1.什么是事务

把一组业务当成一个业务来做;要么都成功,要么都失败,保证业务操作完整性的一种数据库机制

声明式事务

事务的特性ACID

A:原子性,指的是,在一组业务操作下,要么都成功,要么都失败,保证业务组合的完整性;
C:一致性,事务前后的数据要保持一致性
I:隔离性,并发情况下,事务之间要相互隔离
D:持久性,数据一旦保存就是持久的,可反复使用的

在事务控制方面主要分两类
编程式事务

在代码中直接加入事务处理的逻辑,可能需要在代码中显示调用beginTransaction(),commit(),rollback()等事务管理相关的方法
示例:

try{
connetion.autoCommit(false);
...
...
connction.commint();
}catch(Exception e){
connction.rollback();
}

声明式事务

在方法的外部添加注释或者直接在配置文件中定义,将事务管理代码从业务代码中分离出来,以声明的方式来实现事务管理,spring的AOP恰巧可以完成此类功能,事务管理代码的固定模式作为一种横切点关注,通过AOP方法模块化,进而实现声明式事务

spring声明式事务配置

Spring从不同的事务管理API中抽象出了一整套事务管理机制,让事务管理代码从特定的事务技术中独立出来.开发人员通过配置的方式进行事务管理,而不必了解其底层是如何实现的.
Spring的核心事务管理抽象是PlatformTransactionManager。它为事务管理封装了一组独立于技术的方法.无论使用Spring的哪种事务管理策略(编程式或声明式),事务管理器都是必须的.
事务管理器可以以普通的bean的形式声明在Spring IOC容器中

1.在配置文件中增加事务管理器,和数据库相关配置

示例
添加数据库相关配置和jdbcTemplate配置

  
    
    
        
        
        
        
    
    
    
        
    

添加事务控制配置


    
        
    

    

2.对需要进行事务的类,方法使用@Transactional进行标注

-1. @Transactional标注在类上时,表示当前类的所有方法都运用了事务
-2. @Transactional标注在方法上时,表示只有当前方法使用事务

注意:

可以类和方法上面同时都存在, 如果类和方法都存在@Transactional会以方法的为准,如果方法上面没有@Transactional会以类上面的为准

建议:

@Transactional写在方法上面,控制粒度更细, 建议@Transactional写在业务逻辑层上,因为只有业务逻辑层才会有嵌套调用的情况。

示例

    /**
     * 转账
     *
     * @param add_id        转入人id
     * @param sub_id        转出人id
     * @param changeBalance 转账金额
     * @return
     */
    @Override
    @Transactional(isolation = Isolation.REPEATABLE_READ)//给方法执行添加事务
    public Integer transfer(Integer add_id, Integer sub_id, Integer changeBalance) {
        Integer result = accountDao.addBalance(add_id, changeBalance);
        result += accountDao.subBalance(sub_id, changeBalance);
        return result;
    }

事务配置的属性

@Transactional的源码为

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Transactional {
    @AliasFor("transactionManager")
    String value() default "";

    @AliasFor("value")
    String transactionManager() default "";

    Propagation propagation() default Propagation.REQUIRED;

    Isolation isolation() default Isolation.DEFAULT;

    int timeout() default -1;

    boolean readOnly() default false;

    Class[] rollbackFor() default {};

    String[] rollbackForClassName() default {};

    Class[] noRollbackFor() default {};

    String[] noRollbackForClassName() default {};
}

各个属性为:

1.isolation:设置事务的隔离级别
2.propagation:事务的传播行为
3.noRollbackFor:哪些异常事务可以不回滚
4.noRollbackForClassName:发生异常不会回滚的类名,填写的参数是全类名
5.rollbackFor:哪些异常事务需要回滚
6.rollbackForClassName:填写的参数是全类名
7.readOnly:设置事务是否为只读事务
8.timeout:事务超出指定执行时长后自动终止并回滚,单位是秒

1)设置隔离级别:isolation

隔离级别是用来解决并发事务所产生一些问题的一种设定,不同的隔离级别应对不同的并发下产生问题的处理方案;

并发下可能产生的问题
1.脏读:

概念:一个事务,读取了另一个事务中没有提交的数据,会在本事务中产生的数据不
一致的问题
对应隔离级别处理方案:使用隔离级别"读已提交"可以进行处理,使得事务之间只读取其他事务提交后的信息,而不去获取未提交的数据,从而处理脏读问题

@Transactional(isolation = Isolation.READ_COMMITTED)

2.不可从重复读

概念:一个事务中,多次读取相同的数据, 但是读取的结果不一样, 会在本事务中产生数据不一致的问题
对应隔离级别处理方案:使用隔离级别"重复读"可以进行处理,使用行锁的方式,在事务执行期间,禁止其他事务对这个数据进行操作,让事务在一次更新过程中可以读取到相同的值

@Transactional(isolation = Isolation.REPEATABLE_READ)

3.幻读:

概念:一个事务中,多次对数据进行整表数据读取(统计),但是结果不一样, 会在本事务中产生数据不一致的问题。
对应隔离级别处理方案:使用隔离级别"串行化"可以进行处理

@Transactional(isolation = Isolation.SERIALIZABLE)

注意:

串行化事务隔离级别后在事务执行期间,会禁止其他事务对表进行添加,更新,删除等操作,确实避免了任何并发问题,但是效率十分低下

在不设置事务隔离的情况下不同数据库的默认隔离级别是不同的
oracle默认为读已提交,可已通过以下语句查看隔离级别

SELECT s.sid, s.serial#,
CASE BITAND(t.flag, POWER(2, 28))
WHEN 0 THEN 'READ COMMITTED'
ELSE 'SERIALIZABLE'
END AS isolation_level
FROM v$transaction t
JOIN v$session s ON t.addr = s.taddr AND s.sid = sys_context('USERENV', 'SID');

mysql默认隔离级别为重复读,可以通过以下语句查看

SELECT @@tx_isolation;
2)事务的传播性:propagation

事务的传播特性

指的是当一个事务方法被另一个事务方法调用时,这个事务方法的处理方式

spring的事务传播行为有如下属性选择具体如下:

事务传播行为类型 外部不存在事务 外部存在事务 操作方式
REQUIRED(默认) 开启新的事务 融合到外部事务中 @Transactional(propagation = Propagation.REQUIRED)适用增删改查
SUPPORTS 不开启新的事务 融合到外部事务中 @Transactional(propagation = Propagation.SUPPORTS)适用查询
REQUIRES_NEW 开启新的事务 挂起外部事务,创建新的事务 @Transactional(propagation = Propagation.REQUIRES_NEW)适用内部事务和外部事务不存在业务关联情况,如日志
NOT_SUPPORTED 不开启新的事务 挂起外部事务 @Transactional(propagation =Propagation.NOT_SUPPORTED)不常用
NEVER 不开启新的事务 抛出异常 @Transactional(propagation = Propagation.NEVER )不常用
MANDATORY 抛出异常 融合到外部事务中 @Transactional(propagation = Propagation.MANDATORY)不常用

示例

    /**
     * 加钱
     *
     * @param id           人员id
     * @param changBalance 增加金额
     * @return
     */
    @Override
    @Transactional(propagation= Propagation.REQUIRED)
    public Integer addBalance(Integer id, Integer changBalance) {
        return accountDao.addBalance(id, changBalance);
    }
3)超时属性:timeout

概念:

指定事务等待的最长时间单位为秒

作用:

当前事务访问数据时,有可能访问的数据被别的数据进行加锁的处理,那么此时事务就必须等待,如果等待时间过长给用户造成的体验感差

示例

/**
     * 加钱
     *
     * @param id           人员id
     * @param changBalance 增加金额
     * @return
     */
    @Override
    @Transactional(propagation= Propagation.REQUIRED,timeout = 2)
    public Integer addBalance(Integer id, Integer changBalance) {
        return accountDao.addBalance(id, changBalance);
    }
4)设置事务只读:readOnly

使用场景:

基本只会使用在业务查询之中
如果你一次执行单条查询语句,则没有必要启用事务支持,数据库默认支持SQL执行期间的读一致性;
如果你一次执行多条查询语句,例如统计查询,报表查询,在这种场景下,多条查询SQL必须保证整体的读一致性,否则,在前条SQL查询之后,后条SQL查询之前,数据被其他用户改变,则该次整体的统计查询将会出现读数据不一致的状态,此时,应该启用事务支持(如:设置不可重复度、幻影读级别)

示例

@Override
    @Transactional(readOnly = true)
    public Account selectById(Integer id) {
        return accountDao.selectById(id);
    }
5)异常属性noRollbackFor,rollbackFor等

设置当前事务出现的那些异常就进行回滚或者提交
默认对于RuntimeException 及其子类 采用的是回滚的策略
默认对于Exception 及其子类 采用的是提交的策略。

noRollbackFor:设置哪些异常不回滚
rollbackFor:设置哪些异常回滚
示例:

@Override
    @Transactional(readOnly = true,rollbackFor = {FileNotFoundException.class})
    public Account selectById(Integer id) {
        return accountDao.selectById(id);
    }
6)在实战中事务的使用方式

如果当前业务方法是一组 增、改、删 可以这样设置事务

@Transactional

如果当前业务方法是一组 查询 可以这样设置事务

@Transactionl(readOnly=true)

如果当前业务方法是单个 查询 可以这样设置事务

@Transactionl(propagation=propagation.SUPPORTS ,readOnly=true)

3基于xml的事务配置









        
        
    
    
        
        
            
            
            
            
        
    

总结

1.什么是事务
2.声明式事务
3.spring的事务配置
4.spring基于注释的事务实现
5.spring基于xml配置的事务实现

你可能感兴趣的:(spring基础事务学习)