mybatis原理探究

jdbc数据库运行流程:

 

JDBC有哪三种statement接口:

Statement

1、Statement接口提供了执行语句和获取结果的基本方法; 2、Statement继承自Wrapper;3、普通的不带参的查询SQL;支持批量更新,批量删除; 

4、Statement每次执行sql语句,数据库都要执行sql语句的编译 ,最好用于仅执行一次查询并返回结果的情形,效率高于PreparedStatement。 

PreparedStatement

1、PreparedStatement接口添加了处理 IN 参数的方法; 2、PreparedStatement继承自Statement;3、可变参数的SQL,编译一次,执行多次,效率高;  4、安全性好,有效防止Sql注入等问题; 5、支持批量更新,批量删除;  6. 在执行可变参数的一条SQL时,PreparedStatement比Statement的效率高,因为DBMS预编译一条SQL当然会比多次编译一条SQL的效率要高。 7  对于多次重复执行的语句,使用PreparedStament效率会更高一点,并且在这种情况下也比较适合使用batch; 8.  代码的可读性和可维护性。

CallableStatement

1、CallableStatement接口添加了处理 OUT 参数的方法。2、继承自PreparedStatement,支持带参数的SQL操作; 3、支持调用存储过程,提供了对输出和输入/输出参数(INOUT)的支持; 

Mybatis整体流程:

1. mybatis配置文件:SqlMapConfig.xml,此文件作为mybatis的全局配置文件,配置了mybatis的运行环境等信息。Mapper.xml为mybatis的sql映射文件,配置了操作数据库的sql语句,该文件在SqlMapConfig.xml中加载。

2. SqlSessionFactory:通过mybatis环境等配置信息构造SqlSessionFactory,即会话工厂

3. sqlSession:通过会话工厂创建sqlSession即会话,程序员通过sqlsession会话接口对数据库进行增删改查操

4. Executor执行器:mybatis底层自定义了Executor执行器接口来具体操作数据库,Executor接口有两个实现,1个是基本执行器(默认)、另一个是缓存执行器,sqlsession底层是通过executor接口操作数据库的。

5. Mapped Statement:它也是mybatis一个底层封装对象,它包装了mybatis配置信息及sql映射信息等。mapper.xml文件中1个select\insert\update\delete标签对应1个Mapped Statement对象,select\insert\update\delete标签的id即是Mapped statement的id。

  • Mapped Statement对sql执行输入参数进行定义,包括HashMap、基本类型、pojo,Executor通过Mapped Statement在执行sql前将输入的java对象映射到sql中,输入参数映射就是jdbc编程中对preparedStatement设置参数。
  • Mapped Statement对sql执行输出结果进行定义,包括HashMap、基本类型、pojo,Executor通过Mapped Statement在执行sql后将输出结果映射至java对象中,输出结果映射过程相当于jdbc编程中对结果的解析处理过程

sqlSessionFactory创建流程:

对应的动作:SqlSessionFactoryBuilder().build;

SqlSessionFactoryBuilder:利用建造者的身份提供多个创建sqlSessionFactory的方法,总体上分为两种,根据字符流创建与根据字节流创建。但是归根结底还是由XMLConfigBuilder来完成具体的工作。

XMLConfigBuilder:专门来解析全局配置文件的解析器
1 解析</properties>标签
2 解析</settings>标签
3 解析</typeAliases>标签
4 解析</plugins>标签
5 解析</environments>标签
6 解析</mappers>标签

XMLMapperBuilder:从映射文件中的<mapper>根标签开始解析,直到完整的解析完毕
1 获取<mapper>标签的namespace值,也就是命名空间
2 解析<cache-ref>子标签
3 解析<cache>子标签
4 解析<parameterMap>子标签
5 解析<resultMap>子标签
6 解析<sql>子标签,也就是SQL片段 XPATH
7 解析<select>\<insert>\<update>\<delete>子标签 创建MappedStatement对象 由XmlStatementBuilder具体完成

8 创建MapperProxy并与namespace绑定

XmlStatementBuilder:
1 获取statement的id属性(特别关键的值)
2 获取入参类型
3 别名处理,获取入参对应的Java类型
4 获取ResultMap
5 别名处理,获取返回值对应的Java类型
6 设置默认StatementType为Prepared,该参数指定了后面的JDBC处理时,采用哪种Statement
7 解析SQL命令类型是什么?确定操作是CRUD中的哪一种
8 是否查询语句,决定是否用缓存
9 创建SqlSource,解析SQL,封装SQL语句(未参数绑定)和入参信息。由XMLScriptBuilder具体完成
10 通过MapperBuilderAssistant构建者助手的addMappedStatement,创建MappedStatement对象。具体要实现由MappedStatement类的Builder方法完成。

XMLScriptBuilder:
1 创建SqlSource、
2 初始化动态SQL中的节点处理器XMLScriptBuilder、
3 解析select\insert\ update\delete标签中的SQL语句,最终将解析到的SqlNode封装到MixedSqlNode中的List集合中,
将带有${}号的SQL信息封装到TextSqlNode,将带有#{}号的SQL信息封装到StaticTextSqlNode
将动态SQL标签中的SQL信息分别封装到不同的SqlNode中
4 如果SQL中包含${}和动态SQL语句,则将SqlNode封装到DynamicSqlSource
5 如果SQL中包含#{},则将SqlNode封装到RawSqlSource中,最后将解析之后的SQL信息,封装到StaticSqlSource

 

SqlSession创建流程:

对应的动作:sqlSessionFactory().openSession

1 从configuration中获取数据源环境信息environment
2 根据environment获取事务工厂TransactionFactory
3 通过TransactionFactory创建JdbcTransaction或者ManagedTransaction实例 tx
4 创建Executor执行器【批处理执行器、可重用执行器、简单执行器、使用缓存执行器】,具体创建那个哪种执行器根据执行类型来决定.  其中缓存执行器通过批处理执行器、可重用执行器、简单执行器中的一个通过组合模式来实现.
5 创建DefaultSqlSession

 

Mapper代理创建流程:

对应的动作:sqlsession.getMapper

sqlsession.getMapper >> configuration.getMapper >> mapperRegistry.getMapper, 随后根据Mapper接口的类型,从mapperRegistry该类的knownMappers这一Map集合中获取Mapper代理对象工厂MapperProxyFactory

通过MapperProxyFactory的newInstance方法, 其内部通过如下方法:

new MapperProxy<>(sqlSession, mapperInterface, methodCache);

创建了一个mapperProxy(InvocationHandler的实现类),  最后通过Proxy的如下方法:

Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);

创建基于JDK实现的MapperProxy

Mapper代理执行流程(以defaultSqlSession执行select接口为例)

0 执行代理的invoke方法,进而通过DefaultSqlSession执行sql语句
1 根据传入的statementId,获取MappedStatement对象
2 创建缓存key
3 从一级缓存中获取数据,如果一级缓存没有数据,则从数据库查询数据
4 创建RoutingStatementHandler,并在RoutingStatementHandler类中初始化delegate类(SimpleStatementHandler、PreparedStatementHandler)
5 通过StatementHandler创建sql连接、创建Statement(PreparedStatement、Statement、CallableStatement),并调用自身的parameterize方法对statement设置参数
6 执行SQL语句(已经设置过参数),并且映射结果

 

DefaultParameterHandler的setParameters将动态sql中的?替换为传入的参数

SQL查询语句的执行是由SqlSession分发交由Executor托管执行,调度StatementHandler负责JDBCstatement操作,之后下发给ParameterHandler负责对用户传递参数进行转化处理SQL参数,再接着执行SQL语句,最后通过ResultSetHandler对返回结果进行封装处理返回。

posted @   小兵要进步  阅读(53)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix

侧边栏
点击右上角即可分享
微信分享提示