Spring JDBC 编程式事务

编程式事务管理是通过编写代码实现的事务管理,包括定义事务的开始、正常执行后的事务提交和异常时的事务回滚。

Spring 出现以前,编程式事务管理是基于 POJO 应用的唯一选择。在 Hibernate 中,我们需要在代码中显式调用 beginTransaction()、commit()、rollback() 等事务管理相关的方法,这就是编程式事务管理。而通过 Spring 提供的事务管理 API,我们可以在代码中灵活控制事务的执行。

下面根据在《Spring事务》一节讲解的 PlatformTransactionManager、TransactionDefinition 和 TransactionStatus 三个核心接口,通过编程的方式实现事务管理。

SQL:

INSERT INTO account (username,salary) VALUES ('Bob',3000);
INSERT INTO account (username,salary) VALUES ('Make',3000);

DAO层,在OrdersDao中注入jdbcTemplate,实现数据库操作:

@Repository
public class OrdersDao {
    // 注入jdbcTemplate模板对象
    @Autowired
    private JdbcTemplate springJdbcTemplate;

    /**
     * Make减去1000
     */
    public void reduceMoney() {
        String sql = "update account set salary=salary-? where username=?";
        springJdbcTemplate.update(sql, 1000, "Make");
    }

    /**
     * Bob增加1000
     */
    public void addMoney() {
        String sql = "update account set salary=salary+? where username=?";
        springJdbcTemplate.update(sql, 1000, "Bob");
    }
}

Service层,OrdersService接口

public interface OrdersService {
    //转账操作
    void accountMoney();
}

具体实现,OrdersServiceImpl

@Service
public class OrdersServiceImpl implements OrdersService{

    @Autowired
    private OrdersDao ordersDao;

    @Autowired//事务管理器
    private DataSourceTransactionManager transactionManager;

    // 调用dao的方法,业务逻辑,写转账业务
    public void accountMoney() {
        TransactionDefinition def = new DefaultTransactionDefinition();
        // getTransaction()用于启动事务,返回TransactionStatus实例对象
        TransactionStatus status = transactionManager.getTransaction(def);//开启事务
        // 也可以不传def,getTransaction会创建默认的DefaultTransactionDefinition
        //TransactionStatus status = transactionManager.getTransaction(null);
        try {
            // 1-Bob增加1000
            ordersDao.addMoney();
            // 2-加入出现异常如下面int
            int i=10/0; //(银行中可能为突然停电等...)
            // 3-Make减少1000
            ordersDao.reduceMoney();
            transactionManager.commit(status);//提交事务
        } catch (Exception e) {
            transactionManager.rollback(status);//回滚事务
            throw e;
        }
    }
}

application.properties

jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/springtemplate?useSSL=false
jdbc.username=root
jdbc.password=root

具体配置类,JdbcConfig 

@Configuration
public class JdbcConfig {
    @Value("${jdbc.driverClass}")
    private String driver;

    @Value("${jdbc.url}")
    private String url;

    @Value("${jdbc.username}")
    private String username;

    @Value("${jdbc.password}")
    private String password;

    /*数据源*/
    @Bean("dataSource")
    public DriverManagerDataSource getDriverManagerDataSource(){
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName(this.driver);
        dataSource.setUrl(this.url);
        dataSource.setUsername(this.username);
        dataSource.setPassword(this.password);
        return dataSource;
    }

    /*jdbc模板*/
    @Bean("springJdbcTemplate")
    public JdbcTemplate getJdbcTemplate(DataSource dataSource){
        JdbcTemplate jdbcTemplate = new JdbcTemplate();
        jdbcTemplate.setDataSource(dataSource);//配置数据源
        return jdbcTemplate;
    }

    /*事务管理*/
    @Bean("transactionManager")
    public DataSourceTransactionManager dataSourceTransactionManager(DataSource dataSource){
        DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
        transactionManager.setDataSource(dataSource);//配置数据源
        return transactionManager;
    }
}

编写单元测试类

@RunWith(SpringRunner.class)
@SpringBootTest
public class OrdersServiceImplTest {
    @Autowired
    OrdersService ordersService;
    @Test
    public void accountMoney() {
        ordersService.accountMoney();
    }
}

测试结果:

java.lang.ArithmeticException: / by zero

    at com.swadian.spring_learn.service.OrdersServiceImpl.accountMoney(OrdersServiceImpl.java:41)
    at com.swadian.spring_learn.service.OrdersServiceImplTest.accountMoney(OrdersServiceImplTest.java:20)

...

因为出现了异常,所以事务实现了回滚,扣款和加钱操作均没有成功(防止了一方加钱成功另一方扣钱失败的情况),保持了数据的一致性。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

swadian2008

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值