Spring 事务管理--编程式事务(2)

编程式事务 是基于底层的API,如 PlatformTransactionManagerTransactionDefinitionTransactionStatus 等核心接口,开发者完全可以通过编程的方式来进行事务管理。

编程式事务 需要开发者在代码中手动的管理事务的开启、提交、回滚等操作

目前提供两种实现编程式事务的方式:

  • 使用 PlatformTransactionManager(事务管理器)
  • 使用 TransactionTemplate

1. 通过 PlatformTransactionManager 实现的编程式事务

在传统的 Spring 项目,我们需要通过配置XML文件来使用事务,但 SpringBoot 项目,已经自动集成了,我们直接使用即可

<bean class="org.springframework.jdbc.datasource.DriverManagerDataSource" id="dataSource">
    <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
    <property name="url" value="jdbc:mysql://127.0.0.1/demo?useUnicode=true&amp;characterEncoding=utf-8"/>
    <property name="username" value="root"/>
    <property name="password" value="123"/>
</bean>
<bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager" id="txManager">
    <property name="dataSource" ref="dataSource"/>
</bean>
<bean class="org.springframework.jdbc.core.JdbcTemplate" id="jdbcTemplate">
    <property name="dataSource" ref="dataSource"/>
</bean>

业务逻辑模拟

@Service
public class DemoService {
    @Autowired
    JdbcTemplate jdbcTemplate;
    
    @Autowired
    PlatformTransactionManager txManager;

    public void update() {
        DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
        TransactionStatus status = txManager.getTransaction(definition);
        try {
            jdbcTemplate.update("update account_tbl set money=money+100 where name='a'");
            // 为了事务回滚,抛运行时异常
            int i = 1 / 0;
            jdbcTemplate.update("update account_tbl set money=money-100 where name='b'");
            // 事务提交
            txManager.commit(status);
        } catch (DataAccessException e) {
            e.printStackTrace();
            // 事务回滚
            txManager.rollback(status);
        }
    }
}

如果我们需要配置事务的隔离性、传播性等,可以在 DefaultTransactionDefinition 对象中进行配置。TransactionDefinition 用来描述事务的具体规则,也称作事务的属性。

DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
// 设置事务隔离级别
/**
   ISOLATION_SERIALIZABLE:
     最高的隔离级别,完全服从ACID的隔离级别,确保阻止脏读、不可重复读以及幻读,也是最慢的事务隔离级别
*/
definition.setIsolationLevel(TransactionDefinition.ISOLATION_SERIALIZABLE);
// 设置传播行为属性
/**
   PROPAGATION_REQUIRED:
     表示当前方法必须运行在事务中。如果当前事务存在,方法将会在该事务中运行。否则,启动一个新的事务
*/
definition.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);

2. 通过 TransactionTemplate 来实现编程式事务

TransactionTemplate 定义:

public class TransactionTemplate extends DefaultTransactionDefinition implements TransactionOperations, InitializingBean {
    // 定义事务控制器
    private PlatformTransactionManager transactionManager;
    ...
}

修改XML配置: 在上面XML配置文件的基础上,再添加以下 TransactionTemplate 的配置

<bean class="org.springframework.transaction.support.TransactionTemplate" id="tranTemplate">
  <property name="transactionManager" ref="txManager"/>
</bean>

直接使用 TransactionTemplate,在 execute 方法的回调匿名类中编写业务逻辑即可,当抛出异常时,将当前事务标注为只能回滚即可

@Service
public class DemoService {
    @Autowired
    JdbcTemplate jdbcTemplate;
    
    @Autowired
    TransactionTemplate tranTemplate;
    
    public void update() {
        tranTemplate.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus status) {
                try {
                    jdbcTemplate.update("update account_tbl set money=money+100 where name='a'");
                    // 为了事务回滚,抛运行时异常
                    int i = 1 / 0;
                    jdbcTemplate.update("update account_tbl set money=money-100 where name='b'");
                } catch (DataAccessException e) {
                    status.setRollbackOnly();     // 当前事务标注为只能回滚
                    e.printStackTrace();
                }
            }
        });
    }
}

注:在 TransactionTemplate 的 execute 方法,如果不需要获取事务执行的结果,则直接使用 TransactionCallbackWithoutResult 类即可,如果要获取事务执行结果,则使用 TransactionCallback

3. 总结

编程式事务由于代码入侵太严重,因此在实际开发中使用比较少,我们在项目中更多的是使用声明式事务。
熟练使用编程式事务,对我们深入了解 Spring的事务管理是非常有帮助的。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值