
文章插图
3.2TransactionStatus
如果现在仅仅是使用了TransactionManager提交和回滚的处理方法,仅仅是Spring提供的事务处理的皮毛所在,而如果要想深入的理解事务处理的特点,那么就需要分析其每一个核心的组成类,首先分析的就是TransactionStatus 。

文章插图
在开启事务的时候会返回有一个TransactionStatus接口实例,而后在提交或回滚事务的时候都需要针对于指定的status实例进行处理,首先来打开这个接口的定义关联结构 。

文章插图
DefaultTransactionStatus是TransactionStatus默认实现的子类而后该类并不是直接实例化的,而是通过事务管理器负责实例化处理的,status所得到的是一个事务的处理标记,而后Spring依照此标记管理事务 。

文章插图
现我们有以下业务,在业务执行过程中,有一部分业务执行失败,正常来说,是执行回滚操作,但是现在我们要让某一个位置之前的执行的sql不回滚 。那么这个功能如何实现呢?
这里就需要用到我们事务的保存点:
@Testpublic void testInsertSavePoint() { // 测试事务的保存点String sql = "insert into yootk.book(title,author,price) values(?,?,?)";TransactionStatus status = transactionManager.getTransaction( // 开启事务new DefaultTransactionAttribute()); // 默认事务属性Object savepointA = null; //保存点try {LOGGER.info("【插入执行结果】:{}", jdbcTemplate.update(sql, "Python入门", "李老师", 99.90));savepointA = status.createSavepoint(); // 创建保存点LOGGER.info("【插入执行结果】:{}", jdbcTemplate.update(sql, "Java入门", null, 99.90));transactionManager.commit(status); // 正常执行 事务提交} catch (DataAccessException e) {// 出现异常 先回滚到保存点 然后在提交保存点之前的事务status.releaseSavepoint(savepointA);// 回滚到保存点transactionManager.commit(status); // 提交throw new RuntimeException(e);}}
4、Spring事务隔离级别Spring面试之中隔离级别的面试问题是最为常见的,也是一个核心的基础所在,但是所谓的隔离级别一定要记住,是在并发环境
访问下才会存在的问题 。数据库是一个项目应用中的公共存储资源,所以在实际的项目开发过程中,很有可能会有两个不同的线程(每个线程拥有各自的数据库事务),要进行同一条数据的读取以及更新操作 。

文章插图
下面就通过代码的形式 一步步的揭开他的庐山真面目 。
- 对于事务,
private class BookRowMapper implements RowMapper<Book> {// 对象映射关系@Overridepublic Book mapRow(ResultSet rs, int rowNum) throws SQLException {Book book = new Book();book.setBid(rs.getInt(1));book.setTitle(rs.getString(2));book.setAuthor(rs.getString(3));book.setPrice(rs.getDouble(4));return book;}}@Testpublic void testInsertIsolation() throws InterruptedException { // 测试事务的隔离级别String query = "select bid,title,author,price from yootk.book where bid = ?"; // 查询String update = "update yootk.book set title = ?, author =? where bid =?"; // 根据id修改BookRowMapper bookRowMapper = new BookRowMapper(); // 对Book对象的映射DefaultTransactionDefinition definition =new DefaultTransactionDefinition(); // 创建默认事务对象Thread threadA = new Thread(() -> {TransactionStatus statusA = this.transactionManager.getTransaction(definition); //开始事务Book book = this.jdbcTemplate.queryForObject(query, bookRowMapper, 1); // 查询bid = 1的数据String name = Thread.currentThread().getName();// 获取线程名称System.out.println(11111 + "??????");LOGGER.info("{}【查询结果】:{}", name, book);try {TimeUnit.SECONDS.sleep(2); //等待两秒 让线程B修改之后再查询} catch (InterruptedException e) {throw new RuntimeException(e);}book = jdbcTemplate.queryForObject(query, bookRowMapper, 1); // 再次查询LOGGER.info("{}【查询结果】:{}", name, book);}, "事务线程-A");Thread threadB = new Thread(() -> {TransactionStatus statusB =transactionManager.getTransaction(definition); // 开启事务String name = Thread.currentThread().getName();// 获取线程名称int i = 0;try {i = jdbcTemplate.update(update, "Netty", "李老师", 1);LOGGER.info("{} 执行结果:{}", name, i);transactionManager.commit(statusB); // 提交事务} catch (DataAccessException e) {transactionManager.rollback(statusB); // 回滚事务throw new RuntimeException(e);}}, "事务线程-B");threadB.start();// 启动线程threadA.start();threadA.join();// 等待相互执行完成threadB.join();}
经验总结扩展阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 可爱在性感面前一文不值是什么意思?
- 一文带你读懂小米手环6和7的区别 小米手环7比6多了什么功能
- 教你搞定iPhone手机通话音量小的问题 苹果xr声音小怎么解决方法
- 一文看懂华为充电新技术 华为mate30支持无线充电吗
- 一键搞定OPPO手机微信支付的快速通道 oppo手机扫一扫在哪里
- 苹果如何录入nfc门禁卡 (一文了解iPhone手机添加门禁卡的方法)
- 教你一招搞定手机音量问题 苹果手机声音小怎么解决
- 搞定小米手机死机的方法 小米12pro屏幕死机怎么解决
- 千元搞定大内存高性能,别错过4款 一千左右性价比高的手机
- 一指禅搞定手机插入和调整单元格