Spring3.1.0实现原理分析(二十一).Dao事务分析之集成MyBatis

Stella981
• 阅读 438

       大家好,这篇博客我想分析下Spring是如何集成myBatis的,下篇博客分析集成后DataSourceTransactionManager事务管理的完整流程。spring集成mybatis,spring主要扮演了两个角色,原料供应商和事务管理者,第一个角色是必须扮演的,第二个角色可选,事务也可以由mybatis自己管理。为什么说第一个角色叫原料供应商呢?因为spring想驱动mybatis工作,要给它提供必须的原材料,其中有数据源和配置。mybatis获得了数据源和配置后,就可以生产出自己的DefaultSqlSessionFactory对象,这是一个非常重要的mybatis对象,它用于生产mybatis的DefaultSqlSession。

一. SqlSessionFactoryBean

      那么,负责收取spring提供的原料然后加工成DefaultSqlSessionFactory对象的工作由谁完成呢?它就是SqlSessionFactoryBean,通常我们会在配置文件中这样配置,把SqlSessionFactoryBean定义成单例Bean,传入一个数据源对象和mybatis的配置文件,当然它还提供了一些其它属性,如用于配置mybatis的拦截器或类型处理器,不过通常还是更习惯于提供一个mybatis的配置文件路径,把mybatis的相关配置写在这个文件里。

       SqlSessionFactoryBean实现了Spring的InitializingBean接口,因此它会在完成了自身的创建后获得初始化的机会,其目的就是要在初始化方法中完成mybatis的DefaultSqlSessionFactory对象的创建。我用一张图来表述如何得到DefaultSqlSessionFactory对象。Spring3.1.0实现原理分析(二十一).Dao事务分析之集成MyBatis

       我们从左到右分析上图,最左边从上至下三个对象分别是mybatis环境名称、mybatis事务工厂和数据源。环境名称就是一个字符串,当mybatis和spring集成后,环境名称就是“SqlSessionFactoryBean”,环境名称就是起到一个标识的作用,告诉mybatis目前你被集成到spring了。接下来是SpringManagedTransactionFactory(受spring管理的事务工厂),这个类的作用是生产mybatis的事务对象,被生产的事务对象类型是SpringManagedTransaction(受spring管理的事务)。这个事务对象的特点是它调用spring的DataSourceUtils.getConnection(dataSource)获取数据库连接。照理说,spring已经把数据源传给了mybatis,mybatis为什么还要从spring获取数据库连接呢,目的就是要把可能存在的事务管理工作交由spring处理。在spring中适用于mybatis的事务管理器是DataSourceTransactionManager,在Dao类执行数据库操作前,DataSourceTransactionManager会先执行事务初始化操作,初始化操作的核心就是创建数据库连接对象,然后把连接对象置入LocalThread中,当mybatis向spring请求连接对象时,spring便从LocalThread中返回连接对象,spring控制了连接对象,从而就实现了对事务的控制。

     Spring3.1.0实现原理分析(二十一).Dao事务分析之集成MyBatis

  SqlSessionFactoryBean在InitializingBean接口的afterPropertiesSet()方法中创建完DefaultSqlSessionFactory对象后,会赋值给成员变量。同时SqlSessionFactoryBean还实现了FactoryBean接口,这意味着ID是"sqlSessionFactory"的Bean,其值并非SqlSessionFactoryBean,而是其getObject()方法的返回值,返回值就是在初始化时创建的DefaultSqlSessionFactory。

二. SqlSessionTemplate

        mybatis集成spring一共有4个重要的对象,上面我已经介绍了3个(加粗标红字体),第4个对象是SqlSessionTemplate,它实现了mybatis's SqlSession接口,这个接口提供了各种增删改查方法,可以说是mybatis数据库操作的入口。SqlSessionTemplate对SqlSession接口方法的实现,其实是委托给DefaultSqlSession来完成的,既然如此的话,SqlSessionTemplate负责什么呢? 它负责获取DefaultSqlSession对象,之所以要这样设计是为了实现spring事务管理。当从spring获得连接对象,完成DefaultSqlSession对象的创建后,还需要执行spring事务相关操作,具体看下面过程分析。对于未开启spring事务管理的场景,那么创建完DefaultSqlSession对象后,其它操作是不会执行的。无论是否开启spring事务管理,都是从spring获取连接对象。

    SqlSessionTemplate获取DefaultSqlSession对象的完整过程如下:

    1. 调用TransactionSynchronizationManager.getResource(sessionFactory)方法,尝试从当前线程获取DefaultSqlSession对象,首次访问应该是不存在的,如果存在则直接返回。

    2. 调用DefaultSqlSessionFactory对象方法,创建DefaultSqlSession,在创建DefaultSqlSession过程中一个重要的步骤就是从spring获取数据库连接。

    3. 创建SqlSessionHolder对象,它实现了spring的ResourceHolder(资源持有器接口),其持有的资源就是DefaultSqlSession,在创建SqlSessionHolder时会传入DefaultSqlSession。资源持有器的作用是什么?比如它会记录所持有资源的状态,调用资源的方法,可以把它理解为访问资源的标准接口。

    4. 把SqlSessionHolder绑定到当前线程,key是DefaultSqlSessionFactory对象,绑定资源的操作是调用TransactionSynchronizationManager对象方法完成的,TransactionSynchronizationManager对象的作用是管理事务过程中的线程安全对象,比如资源对象、同步对象、事务名称等。

    5. 创建事务同步对象SqlSessionSynchronization,它持有资源对象SqlSessionHolder,然后把它注册到当前线程。事务同步对象的作用是,在某些特定的环节,比如挂起、恢复、事务完成后,对资源持有器执行特定操作,比如解绑资源持有器。用来图来描述下事务同步对象的作用,以及几个对象之间的相互关系。

Spring3.1.0实现原理分析(二十一).Dao事务分析之集成MyBatis

三. 总结

1. spring启动时会创建SqlSessionFactoryBean对象,它负责接收spring供给的原材料,创建DefaultSqlSessionFactory对象。

2. spring集成mybaits最重要的关键点是,由spring供给mybatis数据库连接对象,目的是要实现事务管理。

点赞
收藏
评论区
推荐文章
blmius blmius
2年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Jacquelyn38 Jacquelyn38
2年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Wesley13 Wesley13
2年前
Java获得今日零时零分零秒的时间(Date型)
publicDatezeroTime()throwsParseException{    DatetimenewDate();    SimpleDateFormatsimpnewSimpleDateFormat("yyyyMMdd00:00:00");    SimpleDateFormatsimp2newS
Wesley13 Wesley13
2年前
4cast
4castpackageloadcsv.KumarAwanish发布:2020122117:43:04.501348作者:KumarAwanish作者邮箱:awanish00@gmail.com首页:
Wesley13 Wesley13
2年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
2年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
2年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
2年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
3个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这