体系结构

MyBatis是一个持久层框架,其体系结构分为三层:基础支持层、核心处理层和接口层。

基础支持层包括数据源模块、事务管理模块、缓存模块、Binding模块、反射模块、类型转换模块、日志模块、资源加载模块和解析器模块。这些模块为MyBatis提供了基础功能,为核心处理层提供了良好的支撑。

核心处理层包括配置解析、参数映射、SQL解析、SQL执行、结果集映射和插件。这些组件共同完成了MyBatis的核心处理逻辑,包括将SQL语句与输入参数进行映射,解析SQL语句,执行SQL语句,并将结果映射回Java对象等。

接口层是MyBatis与上层应用交互的桥梁,包括SqlSession接口。SqlSession是MyBatis中最重要的接口之一,它定义了MyBatis保留给应用的API,用于执行各种数据库操作,如查询、插入、更新和删除等。

在MyBatis的体系结构中,还有一个重要的组成部分是全局配置文件。全局配置文件包含了MyBatis的运行环境等信息,通过解析全局配置文件,MyBatis可以完成基本配置的初始化,并根据配置信息实例化相应的组件。

总的来说,MyBatis的体系结构是一个层次分明、模块化的结构,各层之间相互依赖、协同工作,共同完成了MyBatis的核心功能和操作数据库的逻辑。通过这种结构,MyBatis能够有效地封装底层的JDBC操作,让用户专注于SQL语句的编写和数据库操作,提高了开发效率和代码的可维护性。

六大解析器

MyBatis的六大解析器Builder分别是:

  1. XMLConfigBuilder:用于构建 MyBatis 的配置信息,包括数据源、事务管理器等信息。
  2. XMLMapperBuilder:用于构建 Mapper 的 XML 配置文件。该 Builder 读取 Mapper 的 XML 文件,将其解析为 SqlSessionFactory 的一个实例,以便在后续的操作中使用。
  3. MapperBuilderAssistant:用于协助构建 Mapper 的 XML 配置文件。该 Builder 提供了一系列方法,用于简化 Mapper XML 文件的构建过程。
  4. XMLStatementBuilder:用于构建 SQL 语句的 Builder。该 Builder 负责解析 SQL 语句,并将其转换为 MyBatis 可以执行的内部表示形式。
  5. XMLScriptBuilder:用于构建 XML 脚本的 Builder。该 Builder 提供了一些方法,用于构建执行 DDL(数据定义语言)操作的 XML 脚本,例如创建表、视图等。
  6. SqlSourceBuilder:用于构建 SQL 语句的源代码。该 Builder 读取 MyBatis 的映射文件中的 <sql> 标签,将其解析为 SqlSource 对象,以便在执行 SQL 语句时使用。

注意:最终解析的都会存入 Configuration 对象中

package org.apache.ibatis.session;

/**
* @author Clinton Begin
*/
public class Configuration { protected Environment environment; protected boolean safeRowBoundsEnabled;
protected boolean safeResultHandlerEnabled = true;
protected boolean mapUnderscoreToCamelCase;
protected boolean aggressiveLazyLoading;
protected boolean multipleResultSetsEnabled = true;
protected boolean useGeneratedKeys;
protected boolean useColumnLabel = true;
protected boolean cacheEnabled = true;
protected boolean callSettersOnNulls;
protected boolean useActualParamName = true;
protected boolean returnInstanceForEmptyRow;
protected boolean shrinkWhitespacesInSql;
protected boolean nullableOnForEach;
protected boolean argNameBasedConstructorAutoMapping; ...
}

全部代码

SQL 脚本

create database test;
create table test.user
(
id int auto_increment
primary key,
user_name varchar(50) not null,
create_time datetime not null
);

mybaits-cofig.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>
<properties resource="db.properties"></properties>
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
<plugins>
<plugin interceptor="com.mcode.plugin.ExamplePlugin" ></plugin>
</plugins>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<!--// mybatis内置了JNDI、POOLED、UNPOOLED三种类型的数据源,其中POOLED对应的实现为org.apache.ibatis.datasource.pooled.PooledDataSource,它是mybatis自带实现的一个同步、线程安全的数据库连接池 一般在生产中,我们会使用c3p0或者druid连接池-->
<dataSource type="POOLED">
<property name="driver" value="${mysql.driverClass}"/>
<property name="url" value="${mysql.jdbcUrl}"/>
<property name="username" value="${mysql.user}"/>
<property name="password" value="${mysql.password}"/>
</dataSource>
</environment>
</environments> <mappers>
<!--1.必须保证接口名(例如IUserDao)和xml名(IUserDao.xml)相同,还必须在同一个包中-->
<package name="com.mcode.mapper"/> <!--2.不用保证同接口同包同名
<mapper resource="com/mybatis/mappers/EmployeeMapper.xml"/> 3.保证接口名(例如IUserDao)和xml名(IUserDao.xml)相同,还必须在同一个包中
<mapper class="com.mybatis.dao.EmployeeMapper"/> 4.不推荐:引用网路路径或者磁盘路径下的sql映射文件 file:///var/mappers/AuthorMapper.xml
<mapper url="file:E:/Study/myeclipse/_03_Test/src/cn/sdut/pojo/PersonMapper.xml"/>-->
</mappers>
</configuration>

db.properties

mysql.driverClass=com.mysql.cj.jdbc.Driver
mysql.jdbcUrl=jdbc:mysql://127.0.0.1/test?characterEncoding=utf8
mysql.user= root
mysql.password= 123456

UserMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.mcode.mapper.UserMapper">
<cache ></cache>
<!-- Mybatis 是如何将 sql 执行结果封装为目标对象并返回的?都有哪些映射形式?-->
<resultMap id="result" type="com.mcode.entity.User">
<id column="id" jdbcType="INTEGER" property="id"/>
<result column="user_name" jdbcType="VARCHAR" property="userName"/>
<result column="create_time" jdbcType="DATE" property="createTime"/>
<!--<collection property="" select=""--> </resultMap>
<!--namespace根据自己需要创建的的mapper的路径和名称填写-->
<select id="selectById" resultMap="result">
select * from user
<where>
<if test="id > 0">
and id = #{id}
</if>
</where>
</select>
</mapper>

User.java

package com.mcode.entity;

import java.time.LocalDateTime;

/**
* ClassName: User
* Package: com.mcode.entity
* Description:
*
* @Author: robin
* @Version: v1.0
*/
public class User {
private int id;
private String userName; private LocalDateTime createTime; public int getId() {
return id;
} public void setId(int id) {
this.id = id;
} public String getUserName() {
return userName;
} public void setUserName(String userName) {
this.userName = userName;
} public LocalDateTime getCreateTime() {
return createTime;
} public void setCreateTime(LocalDateTime createTime) {
this.createTime = createTime;
}
}

UserMapper.java

package com.mcode.entity;

import java.time.LocalDateTime;

/**
* ClassName: User
* Package: com.mcode.entity
* Description:
*
* @Author: robin
* @Version: v1.0
*/
public class User {
private int id;
private String userName; private LocalDateTime createTime; public int getId() {
return id;
} public void setId(int id) {
this.id = id;
} public String getUserName() {
return userName;
} public void setUserName(String userName) {
this.userName = userName;
} public LocalDateTime getCreateTime() {
return createTime;
} public void setCreateTime(LocalDateTime createTime) {
this.createTime = createTime;
}
}

ExamplePlugin.java

package com.mcode.plugin;

/**
* ClassName: ExamplePlugin
* Package: com.mcode.plugin
* Description:
*
* @Author: robin
* @Version: v1.0
*/ import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds; @Intercepts({@Signature( type= Executor.class, method = "query", args ={
MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class
})})
public class ExamplePlugin implements Interceptor { // 分页 读写分离 Select 增删改 public Object intercept(Invocation invocation) throws Throwable {
System.out.println("代理");
Object[] args = invocation.getArgs();
MappedStatement ms= (MappedStatement) args[0];
// 执行下一个拦截器、直到尽头
return invocation.proceed();
} }

App.java

package com.mcode;

import com.mcode.entity.User;
import com.mcode.mapper.UserMapper;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder; import java.io.IOException;
import java.io.Reader; /**
* Hello world!
*
*/
public class App
{
public static void main( String[] args )
{
String resource = "mybatis-config.xml";
Reader reader;
try {
//将XML配置文件构建为Configuration配置类
reader = Resources.getResourceAsReader(resource);
// 通过加载配置文件流构建一个SqlSessionFactory DefaultSqlSessionFactory
SqlSessionFactory sqlMapper = new SqlSessionFactoryBuilder().build(reader);
// 数据源 执行器 DefaultSqlSession
SqlSession session = sqlMapper.openSession();
sqlMapper.getConfiguration();
try {
UserMapper mapper = session.getMapper(UserMapper.class);
System.out.println(mapper.getClass());
User user = mapper.selectById(1);
System.out.println(user.getUserName());
} catch (Exception e) {
e.printStackTrace();
}finally {
session.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}

MyBatis 源码系列:MyBatis 体系结构、六大解析器的更多相关文章

  1. Spring mybatis源码篇章-Mybatis的XML文件加载

    通过阅读源码对实现机制进行了解有利于陶冶情操,承接前文Spring mybatis源码篇章-Mybatis主文件加载 前话 前文主要讲解了Mybatis的主文件加载方式,本文则分析不使用主文件加载方式 ...

  2. Spring源码情操陶冶#task:scheduled-tasks解析器

    承接前文Spring源码情操陶冶#task:executor解析器,在前文基础上解析我们常用的spring中的定时任务的节点配置.备注:此文建立在spring的4.2.3.RELEASE版本 附例 S ...

  3. springMVC源码分析--HandlerMethodReturnValueHandlerComposite返回值解析器集合(二)

    在上一篇博客springMVC源码分析--HandlerMethodReturnValueHandler返回值解析器(一)我们介绍了返回值解析器HandlerMethodReturnValueHand ...

  4. 精尽 MyBatis 源码分析 - MyBatis 初始化(一)之加载 mybatis-config.xml

    该系列文档是本人在学习 Mybatis 的源码过程中总结下来的,可能对读者不太友好,请结合我的源码注释(Mybatis源码分析 GitHub 地址.Mybatis-Spring 源码分析 GitHub ...

  5. 精尽MyBatis源码分析 - MyBatis初始化(二)之加载Mapper接口与XML映射文件

    该系列文档是本人在学习 Mybatis 的源码过程中总结下来的,可能对读者不太友好,请结合我的源码注释(Mybatis源码分析 GitHub 地址.Mybatis-Spring 源码分析 GitHub ...

  6. 精尽 MyBatis 源码分析 - MyBatis 初始化(三)之 SQL 初始化(上)

    该系列文档是本人在学习 Mybatis 的源码过程中总结下来的,可能对读者不太友好,请结合我的源码注释(Mybatis源码分析 GitHub 地址.Mybatis-Spring 源码分析 GitHub ...

  7. 精尽MyBatis源码分析 - MyBatis初始化(四)之 SQL 初始化(下)

    该系列文档是本人在学习 Mybatis 的源码过程中总结下来的,可能对读者不太友好,请结合我的源码注释(Mybatis源码分析 GitHub 地址.Mybatis-Spring 源码分析 GitHub ...

  8. MyBatis源码分析-MyBatis初始化流程

    MyBatis 是支持定制化 SQL.存储过程以及高级映射的优秀的持久层框架.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.MyBatis 可以对配置和原生Map使用简 ...

  9. Spring mybatis源码篇章-Mybatis主文件加载

    通过阅读源码对实现机制进行了解有利于陶冶情操,承接前文Spring mybatis源码篇章-SqlSessionFactory 前话 本文承接前文的内容继续往下扩展,通过Spring与Mybatis的 ...

  10. 精尽MyBatis源码分析 - MyBatis 的 SQL 执行过程(一)之 Executor

    该系列文档是本人在学习 Mybatis 的源码过程中总结下来的,可能对读者不太友好,请结合我的源码注释(Mybatis源码分析 GitHub 地址.Mybatis-Spring 源码分析 GitHub ...

随机推荐

  1. 对话 BitSail Contributor | 刘啸:参与开源,提升自我技术力

    更多技术交流.求职机会,欢迎关注字节跳动数据平台微信公众号,回复[1]进入官方交流群 2022 年 10 月,字节跳动 BitSail 数据引擎正式开源.同期,社区推出 Contributor 激励计 ...

  2. CountDownLatch、CyclicBarrier 使用区别

    主要区别 CountDownLatch:所有子线程完成后,再执行主线程 CyclicBarrier: 所有子线程就绪后,再执行子线程 CountDownLatch 所有子线程完成后,再执行主线程 多线 ...

  3. Java -jar 运行 报 MalformedInputException: Input length = 1

    Intellij IDEA 中运行正常,linux 运行正常, cmd 下运行 报:MalformedInputException: Input length = 1 微服务项目,在Nacos中做了配 ...

  4. mybatis使用oracle进行添加数据的心得

    本次博主主要进行oralce数据库开发,好久不用oracle,有很多知识点也忘的差不多了,本次主要是复习一下工作中主要使用的一些sql语句编写: 查询 查询语句都是正常的,但是需要注意的是oracle ...

  5. OOALV 不同ALV调用相同屏幕

    一.一次创建,多次调用 当使用OOALV开发平台,存在点击不同位置,跳转到一个ALV,除ALV内容不一致以外,其他都一样. 常规方法,即跳转到多少个ALV,就创建多少个SCREEN.而屏幕对应的输入输 ...

  6. CH0304 IncDec Sequence (差分)

    题目链接: https://ac.nowcoder.com/acm/contest/999/B 思路:(见图中解释) AC代码: #include<bits/stdc++.h> using ...

  7. SCOI2005 互不侵犯 (状态压缩入门题)

    使用状态压缩,最好了解 位运算使用 SCOI2005 互不侵犯 ​ 在 \(N\times N\) 的棋盘里面放 \(K\) 个国王,使他们互不攻击,共有多少种摆放方案.国王能攻击到它上下左右,以及左 ...

  8. vivo悟空活动中台-打造 Nodejs 版本的MyBatis

    经典的架构设计可以跨越时间和语言,得以传承. -- 题记 一.背景 悟空活动中台技术文章系列又和大家见面了,天气渐冷,注意保暖. 在往期的系列技术文章中我们主要集中分享了前端技术的方方面面,如微组件的 ...

  9. 一、docker入门(概念)

    系列导航 一.docker入门(概念) 二.docker的安装和镜像管理 三.docker容器的常用命令 四.容器的网络访问 五.容器端口转发 六.docker数据卷 七.手动制作docker镜像 八 ...

  10. scrollIntoView页面滑动特效

    点击左侧的菜单,页面平滑滚动: