MyBatis介绍
以前都是对MyBatis的使用,因为最近开发扩展组件经常要跟MyBatis打交道,需要在一定条件下修改MyBatis的相关执行逻辑,因此对MyBatis的源码研究了一遍,记一下笔记
我们都清楚MyBatis是一个非常强大的半自动化ORM框架,它实现的核心原理是动态代理接口+Mapper.xml实现了ORM操作,为什么说它是半自动化?这是因为它无法摆脱SQL语句的编写,但是又支持Java代码面向接口调用,减少了实现类的编写,虽然在自动化不如Hibernate,但是因为保留了sql语句编写功能,在灵活度和对sql性能优化层面大大优于Hibernate。现在MyBatis算是在ORM框架中使用最多的。
使用示例
单独使用
private static SqlSessionFactory sqlSessionFactory;
//使用mybatis第一步,获取sqlSessionFactory对象
static {
try {
String resource = "mybatis-test/mybatis-config-test.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
public static SqlSession getSqlSession(){
return sqlSessionFactory.openSession();
}
public static void main(String[] args) {
SysConfigMapper mapper = getSqlSession().getMapper(SysConfigMapper.class);
List<SysConfig> sysConfigs = mapper.selectConfigList(new SysConfig());
System.out.println();
}
结合SpringBoot使用
在application.yaml中添加配置信息,SpringBoot会自动根据dataSource配置启动MyBatis
# MyBatis
mybatis:
# 搜索指定包别名
typeAliasesPackage: com.ruoyi.**.domain
# 配置mapper的扫描,找到所有的mapper.xml映射文件
mapperLocations: classpath*:mapper/**/*Mapper.xml
# 加载全局的配置文件
configLocation: classpath:mybatis/mybatis-config.xml
MyBatis-config.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>
<!-- 全局参数 -->
<settings>
<!-- 使全局的映射器启用或禁用缓存 -->
<setting name="cacheEnabled" value="true" />
<!-- 允许JDBC 支持自动生成主键 -->
<setting name="useGeneratedKeys" value="true" />
<!-- 配置默认的执行器.SIMPLE就是普通执行器;REUSE执行器会重用预处理语句(prepared statements);BATCH执行器将重用语句并执行批量更新 -->
<setting name="defaultExecutorType" value="SIMPLE" />
<!-- 指定 MyBatis 所用日志的具体实现 -->
<setting name="logImpl" value="SLF4J" />
<!-- 使用驼峰命名法转换字段 -->
<!-- <setting name="mapUnderscoreToCamelCase" value="true"/> -->
</settings>
<typeAliases>
<package name="com.ruoyi.system.domain"/>
</typeAliases>
<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://localhost:3306/test?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<!--每一个Mapper.XML都需要在Mybatis核心配置文件中注册!-->
<mappers>
<mapper resource="mybatis-test/SysConfigMapper.xml"/>
</mappers>
</configuration>
MyBatis工作流程分析
先简单分析一下MyBatis的工作流程,后面再深入分析实现细节。
-
获取配置信息
在我们使用过程中,主要有两种方式使用MyBatis分别是:单独使用MyBatis框架,使用SpringBoot集成。
(还有使用Spring单独集成的,现在因为基本上用Spring都用SpringBoot了,所以就不单独列出来了)这一步骤的主要目的是生成Configuration实例,并设置相关配置信息,这个类相当重要,它贯穿了整个MyBatis的生命周期,类似Spring框架的Context
单独使用MyBatis框架,一般都是创建
mybatis-config.xml然后将配置信息配置到xml中,通过读取xml,然后解析xml生成Configuration对象,核心API是XMLConfigBuilder#parse。与SpringBoot集成使用,还是SpringBoot自动配置规则,一个xxxAutoConfiguration+xxxProperties搭配实现自动配置。对MyBatis也不例外,MybatisAutoConfiguration+MybatisProperties获取配置信息 然后用Spring的FactoryBean组件实现SqlSessionFactoryBean进行创建SqlSessionFactory。
并且SpringBoot相对强大点的是,你不止可以通过它提供的MybatisProperties在application.yml中设置MyBatis信息配置信息,还可以通过mybatis.configLocation配置引入独立的mybatis-config.xml配置,来兼容某些全局配置和减少适配以前独立使用mybatis框架配置信息。也是在这一步将mapper.xml解析成了相关MappedStatement,用于描述mapper.xml中写的sql语句,包括每个statement的返回值,sql内容等。
-
创建SqlSessionFactory
创建SqlSessionFactory一般没有特殊需求的都是使用的是MyBatis的默认SqlSessionFactoryBuilder#build(org.apache.ibatis.session.Configuration)。
独立使用:
String resource = "mybatis-test/mybatis-config-test.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);SpringBoot中的SqlSessionFactoryBean#buildSqlSessionFactory
// SqlSessionFactoryBean的全局属性 private SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder(); // SqlSessionFactoryBean#buildSqlSessionFactory的返回最后一步 return this.sqlSessionFactoryBuilder.build(targetConfiguration); -
获取Session
获取Session,org.apache.ibatis.session.SqlSessionFactory#openSession(),主要功能是通过dataSource获取一个会话session来执行sql语句。这一步会选择相应的ExecutorType执行具体的语句,以及相关事务操控。一般来说都是使用的DefaultSqlSession如果我们不想使用Mapper.xml,则在这个类里面还提供了一些直接通过方法调用传sql语句执行的一些API。
DefaultSqlSession有个核心方法,也就是getMapper方法,该方法会调用Configuration的getMapper方法,然后通过MapperRegistry动态生成Mapper的代理类。
-
生成代理对象MapperProxy
生成代理类是MapperRegistry来进行生成的,有个专门生成的工厂:MapperProxyFactory,生成的代理类为MapperProxy。
-
执行Mapper代理对象
MapperProxy#invoke,调用Executor执行