MyBatis 是 Java 生态中非常著名的一款 ORM 框架,目前在一线互联网大厂中应用广泛,MyBatis已经成为了一个必会框架。
MyBatis工作原理,如下图所示 :
上面中流程就是MyBatis内部核心流程,一共会经历8大步骤,下面我会详解8大步骤。
第一步:读取MyBatis的配置文件
MyBatis-config.xml为MyBatis的全局配置文件,用于配置数据库连接信息。
如下所示:
<configuration> <!-- 和spring整合后 environments配置将废除 --> <environments default="development"> <environment id="development"> <!-- 使用jdbc事务管理 --> <transactionManager type="JDBC" /> <!-- 数据库连接池 --> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver" /> <property name="url" value="jdbc:mysql://localhost:3306/test?characterEncoding=utf-8" /> <property name="username" value="root" /> <property name="password" value="123456" /> </dataSource> </environment> </environments> <mappers> <mapper resource="sqlMapper/userMapper.xml"/> </mappers> </configuration>
mapper.xml:sql的映射文件,配置了操作数据库的sql语句,此文件需在config.xml中加载。
比如:加载用户映射信息UserMapper.xml。
<mappers> <mapper resource="sqlMapper/userMapper.xml"/> </mappers>
第二步:加载映射文件
SQL的映射文件,配置了操作数据库的SQL语句,需要在MyBatis配置文件MyBatis-config.xml中加载。
MyBatis-config.xml 文件可以加载多个映射文件,每个文件对应数据库中的一张表。
如下所示:
<mappers> <mapper resource="sqlMapper/userMapper.xml"/> </mappers>
MyBatis-config.xml 加载用户表,映射文件为:UserMapper.xml。
第三步:构造会话工厂
通过MyBatis的环境配置信息构建会话工厂SqlSessionFactory,用来开启SqlSession。
SqlSessionFactory是MyBatis框架中的一个接口,主要负责MyBatis框架初始化操作及为开发人员提供SqlSession对象。
它有两个实现类:DefaultSqlSessionFactory和SqlSessionManager,其中SqlSessionManager已被废弃。
在Mybtis初始化的过程中首先会读取MyBatis的核心配置文件,一般创建SqlSessionFactory的代码如下:
//使用 SqlSessionFactoryBuilder 构建 SqlSessionFactory SqlSessionFactory SqlSessionFactory = new SqlSessionFactoryBuilder().build(configuration);
SqlSessionFactoryBuilder通过Configuration对象生成SqlSessionFactory,用来开启SqlSession。
第四步:创建会话对象
由会话工厂创建SqlSession对象,该对象中包含了执行SQL语句的所有方法,SqlSession对象完成和数据库的交互。
SqlSession提供select、insert、update、delete方法,用于完成和数据库的交互。
第五步:Executor执行器
MyBatis底层定义了一个Executor接口来操作数据库,它将根据SqlSession传递的参数动态地生成需要执行的SQL语句,同时负责查询缓存的维护。
Execute执行器起到至关重要的作用,它是真正执行Java与数据库交互的东西,参与了整个SQL查询执行过程中。
主要有三种执行器:
- 简易执行器SIMPLE(不配置就是默认执行器);
- REUSE是一种重用预处理语句;
- BATCH批量更新批量专用处理器
public enum ExecutorType { SIMPLE, REUSE, BATCH }
第六步:MappedStatement对象
在Executor接口的执行方法中有一个MappedStatement类型的参数,该参数是对映射信息的封装,用于存储要映射的SQL语句的id、参数等信息。
在Executor中doQuery()方法返回了封装的结果集,如下所示:
@Override public <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException { Statement stmt = null; try { Configuration configuration = ms.getConfiguration(); StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql); stmt = prepareStatement(handler, ms.getStatementLog()); return handler.<E>query(stmt, resultHandler); } finally { closeStatement(stmt); } }
第七步:输入参数映射
输入映射,是在映射文件中通过parameterType指定输入参数的类型,类型可以是简单类型、hashmap、pojo的包装类型。
假设现在有个比较复杂的查询需求:完成用户信息的综合查询,需要传入查询条件很复杂。
可能包括:用户信息、其它信息,比如:商品、订单等,那么我们单纯的传入一个User就不行了,所以首先我们得根据查询条件,自定义一个新的pojo,在这个pojo中包含所有的查询条件。
package com.MyBatis.entity; public class UserQueryVo { //在这里添加所需要的查询条件 //用户查询条件,这里假设一个User就已经够了 private User user; public User getUser() { return user; } public void setUser(User user) { this.user = user; } //可以包装其他的查询条件,比如订单、商品等 //...... }
第八步:输出结果映射
使用resultType进行输出映射,输出结果类型可以是Map、List等集合类型,只有查询出来的列名和POJO中的属性名一致,该列才可以映射成功。
拆解,后续我将重点分析其核心源码,这样先全局再局部,这样更有利于掌握其核心原理实现,希望这个框架系列能对你有所用。
陈睿mikechen
10年+大厂架构经验,资深技术专家,就职于阿里巴巴、淘宝、百度等一线互联网大厂。
关注「mikechen」公众号,获取更多技术干货!
后台回复【面试】即可获取《史上最全阿里Java面试题总结》,后台回复【架构】,即可获取《阿里架构师进阶专题全部合集》