Mybatis架构相关的知识
如上所示,这是一个简单的Mybaits执行流程.
我们其实可以看到,一直到第三步(Sqlsession)那么一步,这都是我们的程序里需要创建的.而之后的步骤才是底层完成的任务.
这里就有了一个引申的概念,四大对象。
1 executor 调用
StatementHandler
,以此来执行SQL语句。这个是结构图.
BaseExecutor
:这个执行器执行了最基本的功能,其实如果你用debug就能发现。其余几个执行器执行时,也会调用这个BaseExecutor
中的方法。SimpleExecutor
:最简单的执行器,根据对应的sql直接执行即可,不会做一些额外的操作;拼接完SQL之后,直接交给 StatementHandler 去执行。BatchExecutor
:通过批量操作来优化性能。通常需要注意的是批量更新操作,由于内部有缓存的实现,使用完成后记得调用flushStatements
来清除缓存。ReuseExecutor
:可重用的执行器,重用的对象是Statement,也就是说该执行器会缓存同一个sql的Statement,省去Statement的重新创建,优化性能。内部的实现是通过一个HashMap来维护Statement对象的。由于当前Map只在该session中有效,所以使用完成后记得调用
flushStatements
来清除Map。CachingExecutor
:启用于二级缓存时的执行器;采用静态代理;代理一个 Executor 对象。
执行 update 方法前判断是否清空二级缓存;
执行 query 方法前先在二级缓存中查询,命中失败再通过被代理类查询。
它使用StaementHandler实现JDBC的操作的。
2 parameterHandler:
这个主要是对参数进行操作。
public void setParameters(PreparedStatement ps) throws SQLException {
ErrorContext.instance().activity("setting parameters").object(mappedStatement.getParameterMap().getId());
//获取一个SQL语句集合的参数列表
List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
//如果参数列表不为空
if (parameterMappings != null)
{
//循环整个参数列表
for (int i = 0; i < parameterMappings.size(); i++) {
//取出每一个参数
ParameterMapping parameterMapping = parameterMappings.get(i);
//??????
if (parameterMapping.getMode() != ParameterMode.OUT) {
//
Object value;
//`获取javaBean中的属性名称(如果你用javaBean作为参数输入到SQL语句中,SQL不也是会为你分配到相应的sql中嘛。
//这个就是)
String propertyName = parameterMapping.getProperty();
//查询是否有特殊加入的参数
if (boundSql.hasAdditionalParameter(propertyName)) { // issue #448 ask first for additional params
value = boundSql.getAdditionalParameter(propertyName);
} else if (parameterObject == null) {
value = null;
} else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
value = parameterObject;
} else {
MetaObject metaObject = configuration.newMetaObject(parameterObject);
value = metaObject.getValue(propertyName);
}
//获得typeHandler。这是一种可以用来对输入的值进行处理的函数,将java数据类型转化为数据库数据类型。
//你既可以自己定义,Mybatis也为你提供了一些基本的。
TypeHandler typeHandler = parameterMapping.getTypeHandler();
//jdbcType是对应的sql参数(这个是你在XML文件中设置的,用来对应javaType和jdbcType)JDBCtYPE是一个枚举类型
// <result property="FLD_NUMBER" column="FLD_NUMBER" javaType="double" jdbcType="NUMERIC"/>
JdbcType jdbcType = parameterMapping.getJdbcType();
//如果两者都为空
if (value == null && jdbcType == null) jdbcType = configuration.getJdbcTypeForNull();
//
typeHandler.setParameter(ps, i + 1, value, jdbcType);
}
}
}
}
//设置参数
public void setParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException {
如果参数列表为空
if (parameter == null) {
对应的jdbcType为空
if (jdbcType == null) {
可以为空的参数必须设置jdbcType,否则就报错。
throw new TypeException("JDBC requires that the JdbcType must be specified for all nullable parameters.");
}
try {
ps.setNull(i, jdbcType.TYPE_CODE);
} catch (SQLException e) {
throw new TypeException("Error setting null for parameter #" + i + " with JdbcType " + jdbcType + " . " +
"Try setting a different JdbcType for this parameter or a different jdbcTypeForNull configuration property. " +
"Cause: " + e, e);
}
} else {
//根据传入参数的不同,调用不同种类的set函数,让其进行替换。
setNonNullParameter(ps, i, parameter, jdbcType);
}
}
3 ResultSetHandler
对结果进行操作,将SQL的查询加入到java类型之中。
public interface ResultSetHandler {
// 将Statement执行后产生的结果集(可能有多个结果集)映射为结果列表
<E> List<E> handleResultSets(Statement stmt) throws SQLException; <E> Cursor<E> handleCursorResultSets(Statement stmt) throws SQLException;
// 处理存储过程执行后的输出参数
void handleOutputParameters(CallableStatement cs) throws SQLException; }
3. DefaultResultSetHandler
ResultSetHandler的具体实现类是DefaultResultSetHandler,其实现的步骤就是将Statement执行后的结果集,按照Mapper文件中配置的ResultType或ResultMap来封装成对应的对象,最后将封装的对象返回 。
以最常用的 handleResultSets 为例进行简单的分析:
public List<Object> handleResultSets(Statement stmt) throws SQLException {
ErrorContext.instance().activity("handling results").object(mappedStatement.getId()); final List<Object> multipleResults = new ArrayList<Object>(); int resultSetCount = 0;
// 第一个结果集
ResultSetWrapper rsw = getFirstResultSet(stmt);
// 获取 resultMap
List<ResultMap> resultMaps = mappedStatement.getResultMaps();
int resultMapCount = resultMaps.size();
// 判断 ResultMap 是否为空,空则抛异常
validateResultMapsCount(rsw, resultMapCount);
// 处理第一个结果集
while (rsw != null && resultMapCount > resultSetCount) {
ResultMap resultMap = resultMaps.get(resultSetCount);
// 将结果集映射为对应的 ResultMap 对象
handleResultSet(rsw, resultMap, multipleResults, null);
rsw = getNextResultSet(stmt);
cleanUpAfterHandlingResultSet();
resultSetCount++;
} String[] resultSets = mappedStatement.getResultSets();
if (resultSets != null) {
// 多个结果集
while (rsw != null && resultSetCount < resultSets.length) {
ResultMapping parentMapping = nextResultMaps.get(resultSets[resultSetCount]);
if (parentMapping != null) {
String nestedResultMapId = parentMapping.getNestedResultMapId();
ResultMap resultMap = configuration.getResultMap(nestedResultMapId);
handleResultSet(rsw, resultMap, null, parentMapping);
}
rsw = getNextResultSet(stmt);
cleanUpAfterHandlingResultSet();
resultSetCount++;
}
} return collapseSingleResultList(multipleResults);
}
4 StatementHandler:
这个参数操作了SQL语句的整个执行流程。
这个我以前有文章进行过讲解,所以这个就先算了。就不讲了。
既然对于四大接口(四大对象)有了基本的了解。那么我们就看看下面的图片。我想应该不算很难吧。
参数映射部分算是对应:parameterHandler:
XML配置加载部分可以看看如下这张图片:
参数映射部分在这篇文章中
之后是SQL语句执行:
这个步骤在我看来是对应StatementHandler
结果映射则是由ResultSetHandler
完成的.
(当然,这个就是理解一下四大对象在Mybatis中发生什么作用)
各种常用的Mybatis主要作用。
- BoundSql类,封装mybatis最终产生sql的类,包括sql语句,参数,参数源数据等参数:
- Configuration类:就像是MyBatis的总管,里面包含了所有的信息。无论是连接
Mybatis架构相关的知识的更多相关文章
- JAVA WEB快速入门之从编写一个基于SpringBoot+Mybatis快速创建的REST API项目了解SpringBoot、SpringMVC REST API、Mybatis等相关知识
JAVA WEB快速入门系列之前的相关文章如下:(文章全部本人[梦在旅途原创],文中内容可能部份图片.代码参照网上资源) 第一篇:JAVA WEB快速入门之环境搭建 第二篇:JAVA WEB快速入门之 ...
- 【RAC】RAC相关基础知识
[RAC]RAC相关基础知识 1.CRS简介 从Oracle 10G开始,oracle引进一套完整的集群管理解决方案—-Cluster-Ready Services,它包括集群连通性.消息和锁. ...
- Linux实战教学笔记19:Linux相关网络知识梳理
第十九节 Linux相关网络知识梳理 标签(空格分隔): Linux实战教学笔记-陈思齐 一,前言 一个运维有时也要和网络打交道,所以具备最基本的网络知识,对一个运维人员来说是必要的.但,对于我们的工 ...
- day 28 网络基础相关的知识
1.网络基础相关的知识 架构 C/S 架构: client 客户端 server服务器端 优势: 能充分发挥PC机的性能 B/S 架构: browser 浏览器 server服务器 隶 ...
- JAVA相关基础知识
JAVA相关基础知识 1.面向对象的特征有哪些方面 1.抽象: 抽象就是忽略一个主题中与当前目标无关的那些方面,以便更充分地注意与当前目标有关的方面.抽象并不打算了解全部问题,而只是选择其中的一部分, ...
- Mybatis架构原理(二)-二级缓存源码剖析
Mybatis架构原理(二)-二级缓存源码剖析 二级缓存构建在一级缓存之上,在收到查询请求时,Mybatis首先会查询二级缓存,若二级缓存没有命中,再去查询一级缓存,一级缓存没有,在查询数据库; 二级 ...
- .NET同步与异步之相关背景知识(六)
在之前的五篇随笔中,已经介绍了.NET 类库中实现并行的常见方式及其基本用法,当然.这些基本用法远远不能覆盖所有,也只能作为一个引子出现在这里.以下是前五篇随笔的目录: .NET 同步与异步之封装成T ...
- Mybatis架构学习
Mybatis架构学习 MyBatis 是支持定制化 SQL.存储过程以及高级映射的持久层框架.MyBatis 封装了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.可以对配置和原生Map使用 ...
- Spring Framework------>version4.3.5.RELAESE----->Reference Documentation学习心得----->Spring Framework中web相关的知识(概述)
Spring Framework中web相关的知识 1.概述: 参考资料:官网documentation中第22小节内容 关于spring web mvc: spring framework中拥有自 ...
随机推荐
- Java实现 LeetCode 22 括号生成
22. 括号生成 给出 n 代表生成括号的对数,请你写出一个函数,使其能够生成所有可能的并且有效的括号组合. 例如,给出 n = 3,生成结果为: [ "((()))", &quo ...
- 详解SpringBoot(2.3)应用制作Docker镜像(官方方案)
关于<SpringBoot-2.3容器化技术>系列 <SpringBoot-2.3容器化技术>系列,旨在和大家一起学习实践2.3版本带来的最新容器化技术,让咱们的Java应用更 ...
- js实现初始化调用摄像头
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"% ...
- Java学习之IO流及网络编程
一.字节 1.1字节输入流(java.io.InputStream) 此抽象类是表示字节输入流的所有类的超类 1.1.1定义了所有子类共性的方法: int read() 从输入流中读取数据的下 ...
- kali系统安装后乱码的解决
1.先添加kaili的源地址*(这里推荐了几个源,选一个就可以.打开/etc/apt/sources.list 删除里面自带的所有内容,把你复制的内容添加进去保存就ok了) #中科大 deb http ...
- 50道Java集合经典面试题(收藏版)
前言 来了来了,50道Java集合面试题也来啦~ 已经上传github: https://github.com/whx123/JavaHome 1. Arraylist与LinkedList区别 可以 ...
- python+selenium识别图片验证码
import timeimport pytesseractfrom PIL import Image, ImageEnhancefrom selenium import webdriver url = ...
- Jmeter基础001----jmeter的安装与配置
一.Java环境安装 1.下载jdk----oracal官网 2.JDK版本要求: JMeter2.x- jdk1.6 ...
- python生成批量格式化字符串
在学习tensorflow管道化有关操作时,有一个操作是先生成一个文件名队列.在书上使用了这样的代码: filenames = ['test%d.txt'%i for in in range(1,4) ...
- 个人工作用SQL短句,不定时更新
表字段操作 --一.修改字段默认值 alter table 表名 drop constraint 约束名字 ------说明:删除表的字段的原有约束 alter table 表名 add constr ...