无题
整体执行过程
整体执行过程大致如上图所示。具体的步骤可以拆分成一下内容
首先解析配置,得到 Configuration
创建 SqlSession 回话,用于和数据库完成交互。
SqlSession 中创建不同的 Executor 执行程序。
Executor 中创建 StatementHandler 来调用 jdbc 程序。
Executor 中指定 ParameterHandler 来将 java 类型转化成 jdbc 类型,然后查询数据库,数据库返回的数据通过 ResultSetHandler 把 jdbc 类型转化成 java 类型
具体执行过程分析
整体的执行过程的时序图如上图所示。
创建 mybaties 的环境
本次验证过程中,使用的 mybatis 的编程式方式调用
mybatis-config.xml 文件配置如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<configuration>
<settings>
<setting name="logImpl" value="SLF4J"/>
<!--<setting name="cacheEnabled" value="true" />-->
</settings>
<!--<plugins>-->
<!--<plugin interceptor="com.gupaoedu.mybatis.plugins.TestPlugin">-->
<!--</plugin>-->
<!--</plugins>-->
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://172.16.159.211:3306/user"/>
<property name="username" value="root"/>
<property name="password" value="******"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="TestMapper.xml"/>
</mappers>
</configuration>pom 依赖文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>6.0.6</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.2</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.2</version>
</dependency>
</dependencies>TestMapper 接口
1
2
3
4public interface TestMapper {
User selectByPrimary(Integer id);
}TestMapper.xml 文件
1
2
3
4
5
6
7
8
9
10
11
12
<mapper namespace= "com.mybaties.demo.TestMapper">
<!--<cache-->
<!--eviction="FIFO"-->
<!--flushInterval="60000"-->
<!--size="512"-->
<!--readOnly="true"/>-->
<select id="selectByPrimary" resultType="com.mybaties.demo.User">
select * from user where id = #{id}
</select>
</mapper>测试类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17/**
* 通过接口形式调用
*/
public void Test() throws FileNotFoundException {
FileInputStream fis = new FileInputStream("/Applications/study/java/freamework-study/mybaties/src/main/java/com/mybaties/demo/mybatis-config.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(fis);
SqlSession sqlSession = sqlSessionFactory.openSession();
TestMapper mapper = sqlSession.getMapper(TestMapper.class);
User user = mapper.selectByPrimary(2);
System.out.println(user.toString());
}
开始调试代码分析
我们知道 mabtis 的调用方法是通过接口调用的,但是接口是不能被实例化的,那具体的调用是怎么的呢?
1 | TestMapper mapper = sqlSession.getMapper(TestMapper.class); |
在程序调用上一端代码的时候,进入了 MapperProxy 的 invoke 方法,而且返回的是 MapperProxy 的代理对象,所以我们可以知道 mybatis 是 通过代理模式来调用接口中的方法的。
1 | public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { |
继续跟踪
1 | public Object execute(SqlSession sqlSession, Object[] args) { |
由于我们调用的是 select 方法 ,那么 在将会调用 sqlSession.selectOne 的方法,selectOne 方法的具体实现在 selectList
1 | public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) { |
sqlSession 找到对应的 MappedStatement 对象,然后委派给 executor 来完成调用
1 | public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException { |
queryFromDatabase 调用 doQuery 方法
1 | public <E> List<E> doQuery(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException { |
调用 jdbc 程序查询数据库,并将 jdbc 类型转成 java 类型,返回查询结果。
1 | public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException { |
总结
总体来说,mybatis 的程序体系并不复杂。SqlSession 代表一次完整的数据库回话,Executor 代表一次查询动作,Executor 通过委派 StatementHandler 来与数据库交互。StatementHandler 又含有 ParameterHandler 和 ResultSetHandler 两个处理器,这两个处理器 完成 jdbc 类型和 java 类型之间的相互转换。