欢迎来到飞鸟慕鱼博客,开始您的技术之旅!
当前位置: 首页知识笔记正文

Spring Boot系列 Spring Boot事务应用详解,佳能相机系列详解

墨初 知识笔记 41阅读

public class MainConfig4 {}

当spring容器启动的时候发现有EnableTransactionManagement注解此时会拦截所有bean的创建扫描看一下bean上是否有Transaction注解类、或者父类、或者接口、或者方法中有这个注解都可以如果有这个注解spring会通过aop的方式给bean生成代理对象代理对象中会增加一个拦截器拦截器会拦截bean中public方法执行会在方法执行之前启动事务方法执行完毕之后提交或者回滚事务。

EnableTransactionManagement 的源码

Target(ElementType.TYPE)Retention(RetentionPolicy.RUNTIME)DocumentedImport(TransactionManagementConfigurationSelector.class)public interface EnableTransactionManagement {  /**  * spring是通过aop的方式对bean创建代理对象来实现事务管理的  * 创建代理对象有2种方式jdk动态代理和cglib代理  * proxyTargetClass为true的时候就是强制使用cglib来创建代理  */ boolean proxyTargetClass() default false;  /**  * 用来指定事务拦截器的顺序  * 我们知道一个方法上可以添加很多拦截器拦截器是可以指定顺序的  * 比如你可以自定义一些拦截器放在事务拦截器之前或者之后执行就可以通过order来控制  */ int order() default Ordered.LOWEST_PRECEDENCE;}
2. 定义事务管理器

事务交给spring管理那么你肯定要创建一个或者多个事务管理者有这些管理者来管理具体的事务比如启动事务、提交事务、回滚事务这些都是管理者来负责的。

spring中使用PlatformTransactionManager这个接口来表示事务管理者。

PlatformTransactionManager多个实现类用来应对不同的环境

JpaTransactionManager 如果你用jpa来操作db那么需要用这个管理器来帮你控制事务。

DataSourceTransactionManager 如果你用是指定数据源的方式比如操作数据库用的是JdbcTemplate、mybatis、ibatis那么需要用这个管理器来帮你控制事务。

HibernateTransactionManager 如果你用hibernate来操作db那么需要用这个管理器来帮你控制事务。

JtaTransactionManager 如果你用的是java中的jta来操作db这种通常是分布式事务此时需要用这种管理器来控制事务。

3. 需使用事务的目标上加Transaction注解 Transaction放在接口上那么接口的实现类中所有public都被spring自动加上事务。Transaction放在类上那么当前类以及其下无限级子类中所有pubilc方法将被spring自动加上事务。Transaction放在public方法上那么该方法将被spring自动加上事务。

Transaction参数介绍

参数描述value指定事务管理器的bean名称如果容器中有多事务管理器PlatformTransactionManager那么你得告诉spring当前配置需要使用哪个事务管理器transactionManager同valuevalue和transactionManager选配一个就行也可以为空如果为空默认会从容器中按照类型查找一个事务管理器beanpropagation事务的传播属性下篇文章详细介绍isolation事务的隔离级别就是制定数据库的隔离级别数据库隔离级别大家知道么不知道的可以去补一下timeout事务执行的超时时间秒执行一个方法比如有问题那我不可能等你一天吧可能最多我只能等你10秒 10秒后还没有执行完毕就弹出一个超时异常吧readOnly是否是只读事务比如某个方法中只有查询操作我们可以指定事务是只读的 设置了这个参数可能数据库会做一些性能优化提升查询速度rollbackFor定义零(0)个或更多异常类这些异常类必须是Throwable的子类当方法抛出这些异常及其子类异常的时候spring会让事务回滚 如果不配做那么默认会在 RuntimeException 或者 Error 情况下事务才会回滚rollbackForClassName同 rollbackFor只是这个地方使用的是类名noRollbackFor定义零(0)个或更多异常类这些异常类必须是Throwable的子类当方法抛出这些异常的时候事务不会回滚noRollbackForClassName同 noRollbackFor只是这个地方使用的是类名 4. 执行db业务操作

在Transaction标注类或者目标方法上执行业务操作此时这些方法会自动被spring进行事务管理。

Componentpublic class UserService {    Autowired    private JdbcTemplate jdbcTemplate;    Transactional    public void insertBatch(String  names) {        jdbcTemplate.update(truncate table t_user);        for (String name : names) {            jdbcTemplate.update(INSERT INTO t_user(name) VALUES (?), name);        }    }}
5. 启动spring容器使用bean执行业务操作
Testpublic void test1() {    AnnotationConfigApplicationContext context  new AnnotationConfigApplicationContext();    context.register(MainConfig4.class);    context.refresh();     UserService userService  context.getBean(UserService.class);    userService.insertBatch(java高并发系列, mysql系列, maven系列, mybatis系列);}
四、Spring编程式事务

通过硬编码的方式使用spring中提供的事务相关的类来控制事务。

编程式事务主要的两种用法

通过PlatformTransactionManager控制事务。通过TransactionTemplate控制事务。 4.1 PlatfornTransactionManager

这种是最原始的方式代码量较大后面其他方式都是针对这种方式的封装

Test    public void test1() throws Exception {        //定义一个数据源        DataSource dataSource  new DataSource();        dataSource.setDriverClassName(com.mysql.jdbc.Driver);        dataSource.setUrl(jdbc:mysql://localhost:3306/int?characterEncodingUTF-8&serverTimezoneUTC);        dataSource.setUsername(root);        dataSource.setPassword(123456);        dataSource.setInitialSize(5);        //定义一个JdbcTemplate用来方便执行数据库增删改查        JdbcTemplate jdbcTemplate  new JdbcTemplate(dataSource);        //1.定义事务管理器给其指定一个数据源可以把事务管理器想象为一个人这个人来负责事务的控制操作        PlatformTransactionManager platformTransactionManager  new DataSourceTransactionManager(dataSource);        //2.定义事务属性TransactionDefinition        // TransactionDefinition可以用来配置事务的属性信息比如事务隔离级别、事务超时时间、事务传播方式、是否是只读事务等等。        TransactionDefinition transactionDefinition  new DefaultTransactionDefinition();        //3.开启事务调用platformTransactionManager.getTransaction开启事务操作得到事务状态(TransactionStatus)对象        TransactionStatus transactionStatus  platformTransactionManager.getTransaction(transactionDefinition);        //4.执行业务操作下面就执行2个插入操作        try {            System.out.println(before:  jdbcTemplate.queryForList(SELECT * from t_user));            jdbcTemplate.update(insert into t_user (name) values (?), test1-1);            jdbcTemplate.update(insert into t_user (name) values (?), test1-2);            //5.提交事务platformTransactionManager.commit            platformTransactionManager.commit(transactionStatus);        } catch (Exception e) {            //6.回滚事务platformTransactionManager.rollback            platformTransactionManager.rollback(transactionStatus);        }        System.out.println(after:  jdbcTemplate.queryForList(SELECT * from t_user));    }
4.2 代码分析 步骤一定义事务管理器PlatformTransactionManager

事务管理器相当于一个管理员这个管理员就是用来帮你控制事务的比如开启事务提交事务回滚事务等等。

spring中使用PlatformTransactionManager这个接口来表示事务管理器

public interface PlatformTransactionManager { //获取一个事务开启事务 TransactionStatus getTransaction(Nullable TransactionDefinition definition)   throws TransactionException; //提交事务 void commit(TransactionStatus status) throws TransactionException; //回滚事务 void rollback(TransactionStatus status) throws TransactionException;}
步骤二定义事务属性TransactionDefinition

定义事务属性比如事务隔离级别、事务超时时间、事务传播方式、是否是只读事务等等。
spring中使用TransactionDefinition接口来表示事务的定义信息有个子类比较常用DefaultTransactionDefinition。

步骤三开启事务

调用事务管理器的getTransaction方法即可以开启一个事务。这个方法会返回一个TransactionStatus表示事务状态的一个对象通过TransactionStatus提供的一些方法可以用来控制事务的一些状态比如事务最终是需要回滚还是需要提交。

步骤四执行业务操作

事务管理器开启事务的时候会创建一个连接将datasource和connection映射之后丢在了ThreadLocal中而JdbcTemplate内部执行db操作的时候也需要获取连接JdbcTemplate会以自己内部的datasource去上面的threadlocal中找有没有关联的连接如果有直接拿来用若没找到将重新创建一个连接而此时是可以找到的那么JdbcTemplate就参与到spring的事务中了。

4.2 TransactionTemplate
Test    public void test2() throws Exception {        //定义一个数据源        DataSource dataSource  new DataSource();        dataSource.setDriverClassName(com.mysql.jdbc.Driver);        dataSource.setUrl(jdbc:mysql://localhost:3306/int?characterEncodingUTF-8&serverTimezoneUTC);        dataSource.setUsername(root);        dataSource.setPassword(123456);        dataSource.setInitialSize(5);        //定义一个JdbcTemplate用来方便执行数据库增删改查        JdbcTemplate jdbcTemplate  new JdbcTemplate(dataSource);        //1.定义事务管理器给其指定一个数据源可以把事务管理器想象为一个人这个人来负责事务的控制操作        PlatformTransactionManager platformTransactionManager  new DataSourceTransactionManager(dataSource);        //2.定义事务属性TransactionDefinitionTransactionDefinition可以用来配置事务的属性信息比如事务隔离级别、事务超时时间、事务传播方式、是否是只读事务等等。        DefaultTransactionDefinition  transactionDefinition  new DefaultTransactionDefinition();        transactionDefinition.setTimeout(10);        //3.创建TransactionTemplate对象        TransactionTemplate transactionTemplate  new TransactionTemplate(platformTransactionManager,transactionDefinition);/**         * 4.通过TransactionTemplate提供的方法执行业务操作         * 主要有2个方法         * 1.executeWithoutResult(Consumer<TransactionStatus> action)没有返回值的需传递一个Consumer对象在accept方法中做业务操作         * 2.<T> T execute(TransactionCallback<T> action)有返回值的需要传递一个TransactionCallback对象在doInTransaction方法中做业务操作         * 调用execute方法或者executeWithoutResult方法执行完毕之后事务管理器会自动提交事务或者回滚事务。         * 那么什么时候事务会回滚有2种方式         * 1transactionStatus.setRollbackOnly();将事务状态标注为回滚状态         * 2execute方法或者executeWithoutResult方法内部抛出异常         * 什么时候事务会提交         * 方法没有异常 && 未调用过transactionStatus.setRollbackOnly();         */        transactionTemplate.executeWithoutResult(new Consumer<TransactionStatus>() {            Override            public void accept(TransactionStatus transactionStatus) {                jdbcTemplate.update(insert into t_user (name) values (?), transactionTemplate-1);                jdbcTemplate.update(insert into t_user (name) values (?), transactionTemplate-2);            }        });        System.out.println(after:  jdbcTemplate.queryForList(SELECT * from t_user));    }

标签:
声明:无特别说明,转载请标明本文来源!