Spring编程式事务(手动创建事务)

Spring编程式事务(手动创建事务)

第一种方式 PlatformTransactionManager

@Test
public void test1() throws Exception {
    
    
    //定义一个数据源
    org.apache.tomcat.jdbc.pool.DataSource dataSource = new org.apache.tomcat.jdbc.pool.DataSource();
    dataSource.setDriverClassName("com.mysql.jdbc.Driver");
    dataSource.setUrl("jdbc:mysql://localhost:3306/javacode2018?characterEncoding=UTF-8");
    dataSource.setUsername("root");
    dataSource.setPassword("root123");
    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"));
}

步骤1:定义事务管理器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;
 
}

步骤2:定义事务属性TransactionDefinition

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

步骤3:开启事务

TransactionStatus transactionStatus = platformTransactionManager.getTransaction(transactionDefinition);

执行了getTransaction后,spring内部会执行一些操作,为了方便大家理解,咱们看看伪代码:

//有一个全局共享的threadLocal对象 resources
static final ThreadLocal<Map<Object, Object>> resources = new NamedThreadLocal<>("Transactional resources");
//获取一个db的连接
DataSource datasource = platformTransactionManager.getDataSource();
Connection connection = datasource.getConnection();
//设置手动提交事务
connection.setAutoCommit(false);
Map<Object, Object> map = new HashMap<>();
map.put(datasource,connection);
resources.set(map);

从上面的代码就可以看出来 spring中的事务 datasource 和 con 是密切相关的

步骤4:执行业务操作

JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);

dataSource 因为这个datasource是和con密切相关的,所以使用jdbcTemplate就是使用了事务

第二种方式TransactionTemplate

@Test
public void test1() throws Exception {
    
    
    //定义一个数据源
    org.apache.tomcat.jdbc.pool.DataSource dataSource = new org.apache.tomcat.jdbc.pool.DataSource();
    dataSource.setDriverClassName("com.mysql.jdbc.Driver");
    dataSource.setUrl("jdbc:mysql://localhost:3306/javacode2018?characterEncoding=UTF-8");
    dataSource.setUsername("root");
    dataSource.setPassword("root123");
    dataSource.setInitialSize(5);
    //定义一个JdbcTemplate,用来方便执行数据库增删改查
    JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
    //1.定义事务管理器,给其指定一个数据源(可以把事务管理器想象为一个人,这个人来负责事务的控制操作)
    PlatformTransactionManager platformTransactionManager = new DataSourceTransactionManager(dataSource);
    //2.定义事务属性:TransactionDefinition,TransactionDefinition可以用来配置事务的属性信息,比如事务隔离级别、事务超时时间、事务传播方式、是否是只读事务等等。
    DefaultTransactionDefinition transactionDefinition = new DefaultTransactionDefinition();
    transactionDefinition.setTimeout(10);//如:设置超时时间10s
    //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种方式:
     * (1)transactionStatus.setRollbackOnly();将事务状态标注为回滚状态
     * (2)execute方法或者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"));
}

注意 ::什么时候事务会回滚,有2种方式

1) 方式1

在execute或者executeWithoutResult内部执行transactionStatus.setRollbackOnly();将事务状态标注为回滚状态,spring会自动让事务回滚

2)方式2

execute方法或者executeWithoutResult方法内部抛出任意异常即可回滚。

猜你喜欢

转载自blog.csdn.net/weixin_46350527/article/details/129145705
今日推荐