源码阅读之Mybatis

传统JDBC的执行流程

1.获取连接
2.构建SQL语句
3.设置参数
4.执行SQL
5.获取返回结果
6.基于结果构建返回对象
7.关闭连接

一方面会硬编码,sql与代码混在一起,不易管理和维护,同时也没办法做统一的东西,比如sql缓存,sql执行统计等,此外根据结果返回对应对象效率也比较低下.

myBatis官网给的例子是这样的

String resource = "org/mybatis/example/mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

SqlSession session = sqlSessionFactory.openSession();
try {
  Blog blog = (Blog) session.selectOne("org.mybatis.example.BlogMapper.selectBlog", 101);
} finally {
  session.close();
}

XML内容如下

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
  <environments default="development">
    <environment id="development">
      <transactionManager type="JDBC"/>
      <dataSource type="POOLED">
        <property name="driver" value="${driver}"/>
        <property name="url" value="${url}"/>
        <property name="username" value="${username}"/>
        <property name="password" value="${password}"/>
      </dataSource>
    </environment>
  </environments>
  <mappers>
    <mapper resource="org/mybatis/example/BlogMapper.xml"/>
  </mappers>
</configuration>

执行流程图如下

15854876-428c59dab2a07b2b.png
MyBatis处理流程.png

具体组件作用

configuration

管理 mysql-config.xml 全局配置关系类

SqlSessionFactory

Session 管理工厂接口

Session

SqlSession 是一个给我们用的接口。 提供了很多操作数据库的方法

Executor

执行器是一个接口(基本执行器、缓存执行器)
作用: SqlSession 内部通过执行器操作数据库

MappedStatement

底层封装对象
作用:对操作数据库存储封装,包括 sql 语句、 输入输出参数

StatementHandler

具体操作数据库相关的 handler 接口

ResultSetHandler

具体操作数据库返回结果的 handler 接口

具体的源码流程如下

返回SqlSessionFactory 其实就是从Configuration 解析
org.apache.ibatis.session.SqlSessionFactoryBuilder.build(java.io.InputStream)
 >org.apache.ibatis.builder.xml.XMLConfigBuilder 构造函数
   >org.apache.ibatis.builder.xml.XMLConfigBuilder.parse
     >org.apache.ibatis.builder.xml.XMLConfigBuilder.parseConfiguration mybatis-config.xml内容
       >org.apache.ibatis.parsing.XPathParser.evaluate
        >org.apache.ibatis.builder.xml.XMLConfigBuilder.mapperElement
         >org.apache.ibatis.session.SqlSessionFactoryBuilder.build(org.apache.ibatis.session.Configuration)
          >org.apache.ibatis.session.defaults.DefaultSqlSessionFactory.DefaultSqlSessionFactory


拿到SqlSession 进行对我们的执行器进行初始化 SimpleExecutor
org.apache.ibatis.session.defaults.DefaultSqlSessionFactory.openSession()
 >org.apache.ibatis.session.defaults.DefaultSqlSessionFactory.openSessionFromDataSource
  >org.apache.ibatis.transaction.TransactionFactory.newTransaction(javax.sql.DataSource, org.apache.ibatis.session.TransactionIsolationLevel, boolean)
    >org.apache.ibatis.session.Configuration.newExecutor(org.apache.ibatis.transaction.Transaction, org.apache.ibatis.session.ExecutorType)
      >org.apache.ibatis.executor.SimpleExecutor
        >org.apache.ibatis.executor.CachingExecutor  一级缓存 自动
          >org.apache.ibatis.plugin.InterceptorChain.pluginAll 责任链模式拦截器   可以基于此做一些处理  比如说通过redis来做全局缓存 而不是使用mybatis自己的


操作数据库
org.apache.ibatis.session.defaults.DefaultSqlSession.selectOne(java.lang.String, java.lang.Object)
 >org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(java.lang.String, java.lang.Object)
   >org.apache.ibatis.session.Configuration.getMappedStatement(java.lang.String)
    >org.apache.ibatis.executor.CachingExecutor.query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler)
     >org.apache.ibatis.executor.CachingExecutor.createCacheKey 缓存的key
      >org.apache.ibatis.executor.CachingExecutor.query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler, org.apache.ibatis.cache.CacheKey, org.apache.ibatis.mapping.BoundSql)
         >org.apache.ibatis.executor.BaseExecutor.queryFromDatabase
           >org.apache.ibatis.executor.BaseExecutor.doQuery
对应我们的StatementHandler处理接口和结果集返回接口ResultSetHandler
             >org.apache.ibatis.executor.statement.PreparedStatementHandler.query
               >org.apache.ibatis.executor.resultset.ResultSetHandler.handleResultSets
                >org.apache.ibatis.executor.resultset.DefaultResultSetHandler
               >

     cache key: id +sql+limit+offsetxxx

使用mapper方式的流程

SqlSession session = sqlSessionFactory.openSession();
try {
  BlogMapper mapper = session.getMapper(BlogMapper.class);
  Blog blog = mapper.selectBlog(101);
} finally {
  session.close();
}

源码流程如下

获取mapper:
org.apache.ibatis.session.defaults.DefaultSqlSession.getMapper
   >org.apache.ibatis.session.Configuration.getMapper
    >org.apache.ibatis.binding.MapperRegistry.getMapper
      >org.apache.ibatis.binding.MapperProxyFactory.newInstance(org.apache.ibatis.session.SqlSession)
        >org.apache.ibatis.binding.MapperMethod.execute

sql:
  org.apache.ibatis.binding.MapperMethod.execute
    >org.apache.ibatis.session.SqlSession.selectOne(java.lang.String, java.lang.Object)
      >org.apache.ibatis.executor.BaseExecutor.query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler)
        >org.apache.ibatis.mapping.MappedStatement.getBoundSql

关于mybatis的xml的配置如下

15854876-1d8845f3b0696413.png
mybatis-xml配置.png
1.属性配置

标签名称

<properties resource="app.properties">

<property name="jdbc.driver" value="com.mysql.jdbc.Driver"/>

</properties>

有三种设置方式,优先级如下

1. 构建sessionFactory 时传递 (优先级:高)

2. 基于resource 属性加载 或 url 加载 (优先级:中)

3.基于 <propertite> 属性设置 (优先级:低)

2.全局参数配置

<settings>

<setting name="mapUnderscoreToCamelCase" value="true" />

</settings>

具体的在mybatis的官网:http://www.mybatis.org/mybatis-3/zh/configuration.html#settings
包含了全局缓存设置等,截图如下

15854876-ddac1910fdedeca8.png
mybatis全局属性设置.png

3.环境配置

<environments default="development">

<environment id="development">

<transactionManager type="JDBC" />

<dataSource type="POOLED" >

<property name="driver" value="${jdbc.driver}" />

<property name="url" value="${jdbc.url}" />

<property name="username" value="${jdbc.username}" />

<property name="password" value="${jdbc.password}" />

</dataSource>

</environment>

</environments>

4.mapper的配置

引用方式如下几种

基于 mapper 引入指定资源文件: resource| url |class 优先级从左往右

基于 package 引入:扫描指定包路径当下的url

mapper 的常用元素
•   select – 映射查询语
•   insert – 映射插入语句
•   update – 映射更新语句
•   sql – 可被其他语句引用的可重用语句块。
•   delete – 映射删除语句
•   resultMap 用来描述如何从数据库结果集中来加载对象。
•   cache – 给定命名空间的缓存配置。
•   cache-ref – 其他命名空间缓存配置的引用。

猜你喜欢

转载自blog.csdn.net/weixin_33716941/article/details/87508088