Mybatis总体流程
(1)加载配置并初始化触发条件:加载配置文件
配置来源于两个地方,一个是配置文件(主配置文件conf. xml, mapper文件*.xml),一个是java代码中的注解,将主配置文件内容解析封装到Configuration,将sql的配置信息加载成为一个mappedstatement对象,存储在内存之中
(2)接收调用请求
触发条件:调用Mybatis提供的API传入参数:为SQL的ID和传入参数对象
处理过程:将请求传递给下层的请求处理层进行处理。
(3)处理操作请求
触发条件:API接口层传递请求过来
传入参数:为SQL的ID和传入参数对象处理过程:
- 根据SQL的ID查找对应的MappedStatement对象。
- 根据传入参数对象解析MappedStatement对象,得到最终要执行的SQL和执行传入参数。
- 获取数据库连接,根据得到的最终SQL语句和执行传入参数到数据库执行,并得到执行结果。
- 根据MappedStatement对象中的结果映射配置对得到的执行结果进入转换处理,并得到最终的处理结果。
- 释放连接资源。
(4)返回处理结果
将最终的处理结果返回。
Mybatis核心构建
核心构建 | 描述 |
SqlSession | 作为MyBatis工作的主要顶层API,表示和数据库交互的会话,完成必要数据库增删改查功能 |
Executor | MyBatis执行器,是MyBatis调度的核心,负责SQL语句的生成和查询缓存的维护 |
StatementHandler | 封装了JDBC Statement操作,负责对JDBC statement的操作,如设置参数、将Statement结果集转换成List集合 |
ParameterHandler | 负责对用户传递的参数转换成JDBC Statement所需要的参数 |
ResultSetHandler | 负责将JDBC返回的ResultSet结果集对象转换成List类型的集合 |
TypeHandler | 负责java数据类型和jdbc数据类型之间的映射和转换 |
MappedStatement | MappedStatement维护了一条<select | update | delete | insert>节点的封装 |
sqlSource | 负责根据用户传递的parameterObject,动态地生成SQL语句,将信息封装到BoundSql对象中,并返回 |
BoundSql | 表示动态生成的SQL语句以及相应的参数信息 |
Mybatis层次结构
代码解析
public class Entry {
public static void main(String[] args) {
MtConfiguration configuration = new MtConfiguration("mybatis-config.properties");
MtSqlSessionFactoryBuilder sqlSessionFactoryBuilder = new MtSqlSessionFactoryBuilder(configuration);
MtSqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build();
MtSqlSession sqlSession = sqlSessionFactory.openSession();
PersonDao personDao = sqlSession.getMapper(PersonDao.class);
Person person = personDao.queryPersonById(1l);
System.out.println(person);
}
}
了解Mybatis使用的同学们,能看出这跟你们常用的Mybatis有什么区别吗?区别还是有的,只是很像有木有。
然后再让大家看看这个仿真版的Mybatis框架由哪些部分组成,下面是框架的代码目录。
从上面的图中可以看到涵盖了executor、plugin、typehandler等基础组件。然后再看下是如何使用的。
解析
有些小伙伴可能会有疑问,怎么才能写出这样的框架呢?这个怎么回答呢,其实写出来只需要你对Mybatis的工作原理有大致的了解,知道那些模块是做什么的又是怎么实现的,然后画个流程图,然后定义需要哪些类和接口去实现,最后只需要将这些定义好的类和接口填空就可以了。
那么现在我们来看看这个仿真Mybatis是怎么工作的,当然需要申明的是这个框架仅仅只是作为了解Mybatis运行原理的一个代码练习,有些地方的代码可能只是为了演示这样的效果,并不一定完全跟原生一样。比如Mybatis需要解析XML,而这里我们投了个懒,直接上properties。这样我们就可以重点关注Myabtis的业务流程啦。
接下来对框架的每个部分进行一个简单的说明,具体还请小伙伴去看代码好好了解然后有什么问题直接在评论区或者私信我就可以了,我保证看到就回复,哈哈。
1.configuration模块
顾名思义,就是框架配置类,用于解析配置文件加载相关环境。这里代码里对配置文件的初始化主要有以下这么一个流程。
public MtConfiguration(String configLocation){
this.configLocation = configLocation;
init();
}
private void init(){
try {
//记载配置文件,这里使用properties代替xml解析
loadConfigProperties();
//初始化数据源信息
initDataSource();
//解析并加载mapper文件
loadMapperRegistory();
//解析加载plugin
initPluginChain();
//解析加载typeHandler
initTypeHandler();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
}
可以看到实例类的时候调用init方法进行初始化,分别加载配置信息、初始化数据源信息、解析并加载mapper文件、解析加载plugin、解析加载typeHandler这几个步骤。具体如何进行小伙伴们可以看下代码实现,代码写得简单,相信你们一看就懂。
2.session模块
这个模块用于用户与框架交互的入口。包括常用的sqlSession、sqlSessionFactory以及sqlSessionFactoryBuilder。这几个类完全是仿照Mybatis的,只是类实现会相对简单很多。至于每个类用来干嘛,这个我在之前的文章中有讲述,这里就不多做赘述啦,只是简单引导讲解框架信息。
3.Mapper映射模块
这个模块主要用来注册我们的mapper映射文件的。
这里需要说明下MapperData这个类,这个类主要记录sql语句和sql语句返回类型信息的。然后MapperRegistory用来保存方法与MapperData的映射关系,这样我们执行某个方法是就能找到对应的Sql语句和对应的返回类型了。这个过程可以结合Mybatis解析mapper.xml的过程去理解。
public class MapperData {
private String sql;
private Class type;
public MapperData(String sql, Class type) {
this.sql = sql;
this.type = type;
}
public String getSql() {
return sql;
}
public void setSql(String sql) {
this.sql = sql;
}
public Class getType() {
return type;
}
public void setType(Class type) {
this.type = type;
}
@Override
public String toString() {
return "MapperData{" +
"sql='" + sql + '\'' +
", resultType=" + type +
'}';
}
4.Executor执行模块
这个模块主要用于执行SQL语句并且结合各种handler处理,然后这里只是写了一简单的执行器类。
5.handler模块
这里模仿Mybatis执行SQL时的过程,stamentHandler用于处理语句集、parameterHandler用于处理参数、resultHandler用于处理结果映射。
6.plugin模块
这里模仿Myabtis插件的工作原理实现的,也就是说这里和原生Mybatis的plugin基本一样,不过这里我又偷了个懒,目前只能实现对executor的拦截。哈哈,别怪我。
7.typeHandler模块
这里模仿Mybatis类型处理的机制,用于javaType到jdbcType的映射处理以及jdbcType到javaType的映射处理,当然这只是演示这样的一种效果,具体实现其实没有像Mybatis那样复杂。你们看代码应该也能看出来。
8.配置模块
这里的对框架的配置使用了简单的properties,主要原因还是简单易懂然后节省时间。