Spring AOP事务管理

1 Spring事务简介

(1) 事务作用:在数据层保障一系列的数据库操作同成功同失败。
(2) Spring事务作用:在数据层或业务层保障一系列的数据库操作同成功同失败。
(3) Spring为了管理事务,提供了一个平台事务管理器 PlatformTransactionManager
public interface PlatformTransactionManager{
    void commit(Transactionstatus status)throws TransactionException;
    //commit是用来提交事务。
    void rollback(Transactionstatus status)throws TransactionException;
    //rollback是用来回滚事务。
}
(4) PlatformTransactionManager只是一个接口,Spring还为其提供了一个具体的实现:
public class DataSourceTransactionManager{}
(5) 从名称上可以看出,我们只需要给它一个DataSource对象,它就可以帮你去在业务层管理事务。
(6) 其内部采用的是JDBC的事务。所以说如果你持久层采用的是JDBC相关的技术,就可以采用这个事务管理器来管理你的事务。
(7) 而Mybatis内部采用的就是JDBC的事务,所以Spring整合Mybatis就采用的这个DataSourceTransactionManager事务管理器。
 

2 快速入门

(1) 在需要被事务管理的方法上添加注解

@Service
public class AccountServiceImpl implements AccountService {
    @Autowired
    private AccountDao accountDao;


    @Transactional
    public void transfer(String out,String in ,Double money) {
        accountDao.outMoney(out,money);
        int i = 1/0;
        //模拟异常
        accountDao.inMoney(in,money);
    }
}

(2) 在JdbcConfig类中配置事务管理器

public class JdbcConfig {
    @Value("${jdbc.driver}")
    private String driver;
    @Value("${jdbc.url}")
    private String url;
    @Value("${jdbc.username}")
    private String userName;
    @Value("${jdbc.password}")
    private String password;


    @Bean
    public DataSource dataSource(){
        DruidDataSource ds = new DruidDataSource();
        ds.setDriverClassName(driver);
        ds.setUrl(url);
        ds.setUsername(userName);
        ds.setPassword(password);
        return ds;
    }

    //配置事务管理器,mybatis使用的是jdbc事务。
    //注意:事务管理器要根据使用技术进行选择,Mybatis框架使用的是JDBC事务,可以直接使用DataSourceTransactionManager。
    @Bean
    public PlatformTransactionManager transactionManager(DataSource dataSource){
        DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
        transactionManager.setDataSource(dataSource);
        return transactionManager;
    }
}

(3) 开启事务注解

//在SpringConfig的配置类中开启。
@Configuration
@ComponentScan("com.itheima")
@PropertySource("classpath:jdbc.properties")
@Import({JdbcConfig.class,MybatisConfig.class})
//开启注解式事务驱动
@EnableTransactionManagement
public class SpringConfig {
}

(4) 运行测试类

会发现在转换的业务出现错误后,事务就可以控制回滚,保证数据的正确性。

(5) 注意

@Transactional可以写在接口类上、接口方法上、实现类上和实现类方法上。
写在接口类上,该接口的所有实现类的所有方法都会有事务。
写在接口方法上,该接口的所有实现类的该方法都会有事务。
写在实现类上,该类中的所有方法都会有事务。
写在实现类方法上,该方法上有事务。
***建议写在实现类或实现类的方法上。
 
 

3 Spring事务角色

(1) 未开启Spring事务管理之前:

AccountDao的outMoney因为是修改操作,会开启一个事务T1。
AccountDao的inMoney因为是修改操作,会开启一个事务T2。
//T1和T2即为事务协调员。
AccountService的transfer没有事务。
如果没有抛出异常,则T1和T2都正常提交,数据正确。
如果在两个方法中间抛出异常,T1因为执行成功提交事务,T2因为抛异常不会被执行就会导致数据出现错误。

(2) 开启Spring事务管理之后:

transfer上添加了@Transactional注解,在该方法上就会有一个事务T。
//T为事务管理员。
AccountDao的outMoney方法的事务T1加入到transfer的事务T中。
AccountDao的inMoney方法的事务T2加入到transfer的事务T中。
这样就保证他们在同一个事务中,当业务层中出现异常,整个事务就会回滚,保证数据的准确性。

(3) 通过上面例子的分析,我们就可以得到如下概念:

事务管理员:发起事务方,在Spring中通常指代业务层开启事务的方法。
//即添加了@Transactional注解的方法。
事务协调员:加入事务方,在Spring中通常指代数据层方法,也可以是业务层方法。
//即添加了@Transactional注解的方法中所被调用的dao或service方法。
//两者本质上仍是事务,若因为事务管理员中的异常或某些原因,某个事务协调员所新建事务的代码根本未被执行,事务也不会执行。

(4) 注意

目前的事务管理是基于DataSourceTransactionManagerSqlSessionFactoryBean使用的是同一个数据源。
 

4 Spring事务属性

(1) 事务属性

<1> readOnly

使用@Transactional(readOnly=true)
作用:设置是否为只读事务,true只读事务,false读写事务,增删改要设为false,查询设为true

<2> timeout

使用@Transactional(timeout=-1)//永不超时
作用:设置事务超时时间,单位秒,在多长时间之内事务没有提交成功就自动回滚,-1表示不设置超时时间。

<3> rollbackFor

使用@Transactional(rollbackFor={NullPointException.class})
作用:设置事务回滚异常(class类),当出现指定异常进行事务回滚。
//并不是所有的异常都会回滚事务,Spring的事务只会对Error异常和RuntimeException异常及其子类进行事务回顾,其他的异常类型是不会回滚的。

<4> rollbackForClassName

使用:同上,格式为字符串。@Transactional(rollbackFor={"NullPointException"})
作用:设置事务回滚异常(String字符串),等同于rollbackFor,只不过属性为异常的类全名字符串。

<5> noRollbackFor

使用@Transactional(noRollbackFor={NullPointException.class})
作用:设置事务不回滚异常(class类),当出现指定异常不进行事务回滚。

<6> noRollbackForClassName

使用:同上格式为字符串。@Transactional(noRollbackFor={"NullPointException"})
作用:设置事务不回滚异常(String字符串),等同于noRollbackFor,只不过属性为异常的类全名字符串。

<7> isolation

使用@Transactional(isolation=Isolation.DEFAULT)
作用:设置事务隔离级别(DEFAULT、READ_UNCOMMITTED、READ_COMMITTED、REPEATABLE_READ、SERIALIZABLE),详情查看MySQL笔记。

<8> propagation

使用@Transactional(propagation=Propagation.可选值)
作用:设置事务传播行为。
详情见下,事务传播行为。
//上面这些属性都可以在@Transactional注解的参数上进行设置。

(2) 事务传播行为

<1> 事务传播行为

事务协调员对事务管理员所携带事务的处理态度。

<2> 事务传播行为的可选值

<2.1> REQUIRED(默认)
若事务管理员新建事务t,则事务协调员加入事务t。
若事务管理员未开启事务,则事务协调员新建事务t。
<2.1> REQUIRES_NEW
若事务管理员新建事务t1,则事务协调员新建事务t2。
若事务管理员未开启事务,则事务协调员新建事务t。
<2.1> SUPPORTS
若事务管理员新建事务t,则事务协调员加入事务t。
若事务管理员未开启事务,事务协调员也不开启事务。
<2.1> NOT_SUPPORTED
若事务管理员新建事务t,则事务协调员不开启事务。
若事务管理员未开启事务,事务协调员也不开启事务。
<2.1> MANDATORY
若事务管理员新建事务t,则事务协调员加入事务t。
若事务管理员未开启事务,则程序报错error。
<2.1> NEVER
若事务管理员开启事务,则程序报错error。
若事务管理员未开启事务,则事务协调员也不开启事务。
<2.1> NESTED
设置savePoint,一且事务回滚,事务将回滚到savePoint处,交由客户响应提交/回滚。
//对于我们开发实际中使用的话,因为默认值需要事务是常态的。根据开发过程选择其他的就可以了,例如案例中需要新事务就需要手工配置。
posted @ 2023-10-17 21:21  10kcheung  阅读(47)  评论(0)    收藏  举报