混合使用的背景

最近项目中需要引入工作流引擎,实现业务和流程设计、流转的解耦。

工作流流引擎选用的是snaker,轻量、易上手、可定制。访问数据库用的是JdbcTemplate 。

项目中原有的持久层框架是Mybatis。

这样就带来一个问题:怎样保证业务逻辑(Mybatis) 和工作流流引擎(JdbcTemplate )处于事务控制中,避免数据异常。

比如:业务单据创建成功后,审批流程启动。如果单据创建成功,审批流程启动异常,事务就应该回滚,否则就成僵尸单据了。

混合事务控制的配置

<!-- 按照正常的Spring事务管理配置即可,黑魔法在框架的扩展上体现。 -->
<tx:annotation-driven proxy-target-class="true" /><bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource" />
</bean>

混合事务控制的分析

首先,事务控制的原理是通过AOP进行事务增强,实现数据连接事务的开启、提交或者回滚。

然后,事务控制的核心是开启事务后,会把对应的Connection 关联到当前的线程中,所有关联的数据库操作,使用的都是这个Connection,才能保证逻辑事务的完整性。

所以,Mybatis 和JdbcTempate 混合事务控制,保证数据一致性,关键就是保证不同框架获取到的是事务开启后的同一个Connection 对象。剩下的就是AOP 拦截器实现提交或者回滚即可。

Insight Mybatis 事务的开启

关键类

org.mybatis.spring.transaction.SpringManagedTransactionFactory

org.mybatis.spring.SqlSessionTemplate.SqlSessionInterceptor

工作原理

/*** 动态代理 SqlSession,拦截对应的方法,事务相关的操作托管给Spring's Transaction Manager* 通过这个InvocationHandler, 把所有的Mybatis 数据库操作的getSqlSession 都委托给Spring 处理,偷天换日。* 核心实现:* 给当前线程绑定一个 SqlSession对象,这样就能够保证后续的持久化操作获取的都是这个 SqlSession对象。*/
private class SqlSessionInterceptor implements InvocationHandler {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {// 从Spring事务管理器获取 sqlSession,或者在需要时创建一个新sqlSession。// Retrieve a sqlSession for the given key that is bound to the current thread.// @see SqlSessionUtils#getSqlSessionSqlSession sqlSession = getSqlSession(...);try {Object result = method.invoke(sqlSession, args);if (!isSqlSessionTransactional(sqlSession, SqlSessionTemplate.this.sqlSessionFactory)) {// force commit even on non-dirty sessions because some databases require// a commit/rollback before calling close()sqlSession.commit(true);}return result;} catch (Throwable t) {// ...}}
}
/*** 管理从Spring's transaction manager 获取的 connection* 如果事务管理是启用状态,那么commit/rollback/close 操作统一交给事务管理器去完成。*/
public class SpringManagedTransaction implements Transaction {@Overridepublic Connection getConnection() throws SQLException {if (this.connection == null) {openConnection();}return this.connection;}/*** Gets a connection from Spring transaction manager and discovers if this* {@code Transaction} should manage connection or let it to Spring.* <p>* It also reads autocommit setting because when using Spring Transaction MyBatis* thinks that autocommit is always false and will always call commit/rollback* so we need to no-op that calls.*/private void openConnection() throws SQLException {// 获取的Connection 操作,会检测是否启用了事务管理器。如果有事务管理器,会给当前线程绑定或者获取一个 Connection对象。 (Will bind a Connection to the thread if transaction synchronization is active)this.connection = DataSourceUtils.getConnection(this.dataSource);this.autoCommit = this.connection.getAutoCommit();this.isConnectionTransactional = DataSourceUtils.isConnectionTransactional(this.connection, this.dataSource);}
}

Insight JdbcTempate 事务的开启

public <T> T execute(CallableStatementCreator csc, CallableStatementCallback<T> action) {// 和Mybatis SpringManagedTransaction 获取Connection 调用同样的方法。Connection con = DataSourceUtils.getConnection(getDataSource());CallableStatement cs = null;try {cs = csc.createCallableStatement(conToUse);applyStatementSettings(cs);T result = action.doInCallableStatement(csToUse);handleWarnings(cs);return result;}catch (SQLException ex) {// ...}finally {JdbcUtils.closeStatement(cs);DataSourceUtils.releaseConnection(con, getDataSource());}
}

总结

  • Mybatis JdbcTemplate 获取Connection 的方式殊途同归,保证获取的是同一个 Connection。
  • Mybatis 事务启用后,会给当前的线程注册两个对象,SqlSession 和 Connection。
  • 如果Spring 事务是否启用的判断方式是根据当前线程的ThreadLocal 是否有初始化
  • 如果需要把事务托管给Spring,最简单的是通过 DataSourceUtils.getConnection 获取连接。
  • 借鉴Spring 框架的集成Mybatis 的方式,为后续的通用设计提供参考。

Insight Mybatis JdbcTemplate 混合事务控制的实现相关推荐

  1. MyBatis中设置事务自动提交

    MyBatis中设置事务自动提交 MyBatis框架是对JDBC的封装,MyBatis中的事务控制方式其本质也是JDBC的setAutoCommit()方法来设置事务提交的方式的. 1.MyBatis ...

  2. SpringBoot(配置druid数据源、配置MyBatis、事务控制、druid 监控)

    SpringBoot 得到最终效果是一个简化到极致的 WEB 开发,但是只要牵扯到 WEB 开发,就绝对不可能缺少 数据层操作,所有的开发都一定秉持着 MVC 设计模式的原则,MVC 里面业务层不可少 ...

  3. SpringBoot整合Mybatis,并实现事务控制

    SpringBoot整合Mybatis,并实现事务控制 1. 在pom文件里添加相关maven文件 <parent><groupId>org.springframework.b ...

  4. java day60【 Spring 中的 JdbcTemplate[会用] 、Spring 中的事务控制 、Spring5 的新特性[了解] 】...

    第1章 Spring 中的 JdbcTemplate[会用] 1.1JdbcTemplate 概述 1.2JdbcTemplate 对象的创建 1.3spring 中配置数据源 1.3.1 环境搭建 ...

  5. SpringMVC与Mybatis集合实现调用存储过程、事务控制

    在SSM框架中经常会用到调用数据库中的存储过程.以及事务控制,下面以保存某单据为例,介绍一下: 1.Oracle中存储过程代码如下(主要逻辑将单据编码自动加1,并将该单据编码返回): CREATE O ...

  6. Spring——DAO层、Spring JDBC、Spring事务控制

    目录 一.Spring对持久层技术支持 1.Spring支持的持久层技术 2.Spring JDBC 2.1. JDBCTemplate类 2.2.Spring JDBC CRUD操作 2.3.Spr ...

  7. Spring的事务控制-基于注解的方式

    模拟转账操作,即Jone减少500,tom增加500 如果有疑问请访问spring事务控制-基于xml方式 1.创建数据表 2.创建Account实体类 public class Account {p ...

  8. spring—事务控制

    编程式事务控制相关对象 PlatformTransactionManager PlatformTransactionManager 接口是 spring 的事务管理器,它里面提供了我们常用的操作事务的 ...

  9. spring编程式和声明式事务控制

    可优先参考:@Transactional Spring 事务的深入学习与使用[两万字] 1. 编程式事务控制 @Autowired private RoleMapper roleMapper;@Aut ...

最新文章

  1. python编写统计选票的程序_使用python编写微信公众号发稿统计程序
  2. 6月数据库排行:PostgreSQL和MongoDB分数罕见下降
  3. C语言关系 是行还是列,C语言行优先和列优先的问题深入分析
  4. C++笔记:select多路复用机制
  5. uniapp+typeScript+vue3.0+vite
  6. UE3 贴图支持及设置
  7. tshark查看、指定网卡
  8. BERT中进行NER为什么没有使用CRF,我们使用DL进行序列标注问题的时候CRF是必备么?...
  9. (转)EOSIO开发(四)- nodeos、keosd与cleos
  10. python super()函数
  11. iphone开蓝牙wifi上网慢_iPhone连接wifi信号满格网速却慢?如何提速
  12. 微大夫感冒舒缓仪亮相“2018健康陕西发展大会”回顾
  13. 一般时序电路设计(次态卡诺图化简法)
  14. 终于解决!——iPhone自带的邮件应用如何绑定163网易邮箱?
  15. java小项目---------银行新用户现金业务办理(运用数据库)
  16. 7、对数组中下标为奇(偶)数的元素进行操作
  17. 【java面试经(架构师设计师)-第9课】网络编程校验方法和加密算法
  18. Java学习打卡第八天——[Collection终结之HashMap,Collections的简介和使用]
  19. 【实验】Oracle 10g RAC生产数据库RMAN方式恢复到异地单机数据库全程记录
  20. vue项目使用xlsx-style导出自定义格式excel

热门文章

  1. TryHackMe | Blue Writeup (超干货详细msf渗透使用指南)
  2. 金融数据类——国内贵金属
  3. 请根据英文单词的第一个字母判断星期几,如果第一个字母是一样的,则继续判断第二个字母。例如如果第一个字母是S,则继续判断第二个字母,如果第二个字母是a,则输出“星期六”。
  4. Java运行环境搭建与Hello world
  5. 基于GAN的图像生成模型
  6. matlab如何根据历年gdp找增长规律,请问如何根据中国统计年鉴数据计算历年的GDP平减指数?...
  7. 激励自己的短句文案乾坤未定你我皆是黑马
  8. 2019年中国银行三年期大额存单的利率是多少?
  9. 2023最新ThinkPHP6开发云梦卡社区系统源码+代码已开源+UI美观
  10. 抓取baidu数字证书