目录
本文概览:本文介绍了mybatis大致实现原理。分为sqlSessionTempalte和@Responsitory两种实现方式
1 底层实现
每一个线程对于一个数据源会生成一个sqlSession,通过这个sqlSession可以执行mapper文件定义的sql。sqlSessionTempalte和@Responsitory两种实现方式都是基于这个底层来实现的,如下图所示:
1. 1 Mapper文件
mapper中一个sql对应一个stament。解析mapper文件时会生成一个map:
- key为sql的id。这里id就是mapper文件的namesapce和sql语句中定义的id两部分拼接组成,这就保证了所有mapper中的sql都有一个唯一的id
- value为生成一个statement所需要的属性MappedStaement。即如<select >中配置的timeout、resultMap、resultType等属性。
1.2 DefaultSqlSession
1、作用
用来执行执行sql,每一个线程对于一个数据源有一个SqlSession。
2、执行一个sql的过程如下
- 根据id从Mapper文件生成的map中找到对应的属性MappedStement。其中id就是mapper中namesapce和sql中id属性的拼接。
- 取当前线程dataSource对应的connection,结合MapperdStament,生成一个stament;
- 执行stament;
- 关闭stament。
2 两种方式实现
2.2 SqlSessionTemplate
1、作用
用来执行update/select等操作。
2、实现
通过sqlSeesionFactory获取当前线程对应数据源的DefalutSqlSession,然后通过DefaultSqlSession来执行。
3、使用SqlSessionTemplate实现Dao
1 2 3 |
<bean id="sqlSession2" class="org.mybatis.spring.SqlSessionTemplate"> <constructor-arg ref="sqlSessionFactory2" /> </bean> |
2.2 MapperScannerConfigurer
1、作用
实现了@Respository方式
2、实现
首先,将每一个定义的dao接口生成一个动态代理对象,放置到IOC容易中。
然后,通过代理对象执行某一个函数,具体逻辑为:
- 根据函数名可以从mapper文件生成的map中获取对应的MappedStatement。根据函数名生成map中key的逻辑为:“包名+类名+函数名”
- 通过sqlSeesionFactory获取当前线程对应数据源的DefalutSqlSession,然后通过DefaultSqlSession来执行。
3、使用
1 2 3 4 5 |
<bean id="mapperScannerConfigurer2" class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <!--配置扫描的dao接口的路径,可以有多个路径,每一个用逗号隔开--> <property name="basePackage" value="dao.mybatis.annotation.datasource2"/> <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory2"/> </bean> |
2.3 比较SqlSessiontTemplate和MapperScannerConfigureer
1、执行的步骤共同点都是一样的,如下
- 第一步 获取一个唯一key。这个key是根据mapper文件的namesapce和一个sql的id拼接生成;
- 第二步 通过DefaulteSqlSession来执行这个key。如下DeflultSqlSession中一个函数,参数statement就是上面的key值。
1public <E> List<E> selectList(String statement)
2、不同点
在上面第一步中获取key的方式是不同的:
- 对于SqlSessiontTemplate,是需要自己指定的key。如下
1 |
sqlSession.<Integer>selectOne("dao.mybatis.annotation.datasource1.StudentDao.count"); |
- @Respository方式,程序自己根据自己定义的dao接口中方法,获取一个key,如下,此时代码,此时对于count这个函数的key就是“包名+类名+函数名”,即dao.mybatis.annotation.datasource1.StudentDao,也是“mapper文件中namesapce的值+sql的id属性”。
12345package dao.mybatis.annotation.datasource1;@Repositorypublic interface StudentDao {int count();}
3 一些总结
1. 在mybtais中,每一个线程中对于一个数据源有一个connection。
(1)通过TreadLocal来存储,key为数据源。
(2)不同mapper中定义的sql,每一个mapper中sql对应一个statmenet,如果他们数据源一样,则对应的connection是同一个。
2. 默认情况下,自动提交会设置为true,此时每一次执行一个stament(mapper中的一个sql),都会进行默认提交。但是这个线程对应dataSouce的connection会一直保留,线程执行完毕之后,连接池会回收这个connection。
(全文完)