MyBatis源码分析-SQL语句执行的完整流程(1)
sql语句执行流程

sql语句执行流程SQL语句执行流程SQL是结构化查询语言的缩写,它是一种用于管理关系型数据库的语言。
在数据库中,SQL语句被用来创建、更新、删除和查询数据。
下面将详细介绍SQL语句执行的流程。
1. 解析阶段当用户输入SQL语句时,首先需要对其进行解析。
解析器会检查语法和拼写错误,并将SQL语句转换为计算机可以理解的格式。
在这个阶段,还会确定要执行的操作类型(如SELECT、INSERT、UPDATE或DELETE)以及要操作的表名和列名。
2. 编译阶段在编译阶段,数据库管理系统(DBMS)会将解析后的SQL语句转换为可执行代码。
这个代码通常称为查询计划或执行计划。
查询计划包含了一系列操作指令,用于读取和修改数据。
3. 优化阶段在优化阶段,DBMS会尝试找到最有效的查询计划。
它会考虑许多因素,如表大小、索引数量和可用内存等。
优化器还可以使用统计信息来估算每个可能的执行计划所需的时间和资源。
4. 执行阶段在执行阶段,DBMS会按照查询计划中指定的顺序读取数据并进行处理。
如果需要,在此期间还可以对数据进行排序、过滤和聚合等操作。
执行阶段还可以包括锁定和事务管理等步骤,以确保数据的一致性和安全性。
5. 返回结果最后,DBMS会将处理后的结果返回给用户。
如果是SELECT语句,结果将是一个数据集,包含满足查询条件的所有行。
如果是INSERT、UPDATE或DELETE语句,则返回受影响的行数。
总结SQL语句执行流程包括解析、编译、优化、执行和返回结果五个阶段。
在每个阶段,DBMS都会进行不同的操作以确保SQL语句能够正确地执行并返回正确的结果。
了解SQL语句执行流程对于优化查询性能和调试错误非常重要。
mybatis工作原理流程

mybatis工作原理流程
MyBatis是一种基于Java的持久化框架,它通过XML或注解的
方式将Java对象映射到数据库中的数据。
MyBatis的工作原理可以简单地概括为以下流程:
1. 配置文件加载
MyBatis的配置文件包含数据源配置、映射文件配置、缓存配置等内容,它通过解析配置文件来获取相关配置信息。
2. SqlSessionFactory创建
SqlSessionFactory是MyBatis的核心接口,它负责创建SqlSession对象,SqlSession对象是与数据库交互的主要接口。
3. SqlSession创建
SqlSession是MyBatis与数据库交互的主要接口,它提供了各
种操作数据库的方法,如插入、更新、删除和查询等。
4. Mapper接口调用
Mapper接口是MyBatis中定义操作数据库的接口,它通过动态
代理方式生成接口的实现类,并调用相应的SQL语句完成数据库操作。
5. SQL语句执行
MyBatis通过动态生成SQL语句,将Java对象与数据库中的数
据进行映射。
在执行SQL语句前,MyBatis会将SQL语句进行预编译,提高SQL语句的执行效率。
6. 数据库操作结果返回
MyBatis通过执行SQL语句,将数据库操作结果返回给Java程
序,Java程序可以根据返回结果进行相应的处理。
以上就是MyBatis的工作原理流程,通过理解MyBatis的工作原理,我们可以更好地使用MyBatis框架进行Java开发。
MyBatis运行动态sql及存储过程

MyBatis运⾏动态sql及存储过程1 利⽤MyBatis进⾏模糊查询在利⽤MyBatis进⾏模糊查询时候。
须要⽤到concat,注意在Oracle中concat连接的是两个參数。
不是三个參数。
持久化类:package com.web.entity;public class Student {private Integer studentId;private String studentName;private Classes classes;public Integer getStudentId() {return studentId;}public void setStudentId(Integer studentId) {this.studentId = studentId;}public String getStudentName() {return studentName;}public void setStudentName(String studentName) {this.studentName = studentName;}public Classes getClasses() {return classes;}public void setClasses(Classes classes) {this.classes = classes;}}dao中⽅法:package com.web.dao;import java.io.InputStream;import java.util.HashMap;import java.util.Map;import org.apache.ibatis.io.Resources;import org.apache.ibatis.session.SqlSession;import org.apache.ibatis.session.SqlSessionFactory;import org.apache.ibatis.session.SqlSessionFactoryBuilder;import com.web.entity.Student;public class StudentDao {private int res=-1;private SqlSession sqlSession=null;public SqlSession getSqlSession(){try{String resource="mybatis-config.xml";InputStream is=Resources.getResourceAsStream(resource);SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(is);sqlSession=sqlSessionFactory.openSession(true);}catch(Exception e){System.out.println("出错");e.printStackTrace();}return sqlSession;}public Student findTStudentByName(Student student){sqlSession=getSqlSession();Student s=sqlSession.selectOne("lk", student);return s;}/*public int getCount(Integer classesid){int result=-1;Map<String, Integer> map=new HashMap<String, Integer>();map.put("classesid", classesid);map.put("studentcount", -1);sqlSession=getSqlSession();sqlSession.selectOne("gc", map);result=map.get("studentcount");return result;}*/}映射⽂件:<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE mapperPUBLIC "-////DTD Mapper 3.0//EN""/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.pb.dao.StudentDao"><!-- <resultMap type="Student" id="ts"><id property="studentId" column="studentId" /><result property="studentName" column="studentName" /><association property="classes" column="classesId"javaType="Classes"><id property="classesId" column="classesId" /><result property="classesName" column="classesName" /></association></resultMap><select id="selectonetoone" resultMap="ts" parameterType="Student">selects.studentid,s.studentname,c.classesnamefromstudent sleft join classes con s.classesid=c.classesidwhere s.studentid=#{studentId}</select> --><select id="lk" resultMap="ts" parameterType="Student">select * from student s where s.studentname like concat(concat('%','h'),'%')</select><!-- <select id="gc" parameterMap="gm" statementType="CALLABLE">call pro_student(?,?)</select><parameterMap type="java.util.Map" id="gm"><parameter property="classesid" mode="IN" jdbcType="INTEGER"/><parameter property="studentcount" mode="OUT" jdbcType="INTEGER"/></parameterMap> --></mapper>2 利⽤MyBatis运⾏存储过程:在映射⽂件⾥定义⼀个parameterMap作为參数,设置statementType="CALLABLE",过程的參数放置?站位符。
MyBatis执行动态SQL语句详解

MyBatis执⾏动态SQL语句详解⼤家基本上都知道如何使⽤ MyBatis 执⾏任意 SQL,使⽤⽅法很简单,例如在⼀个 XXMapper.xml 中:<select id="executeSql" resultType="map">${_parameter}</select>你可以如下调⽤:sqlSession.selectList("executeSql", "select * from sysuser where enabled = 1");或者你可以在 XXMapper.java 接⼝中定义如下⽅法:List<Map> executeSql(String sql);然后使⽤接⼝调⽤⽅法:xxMapper.executeSql("select * from sysuser where enabled = 1");上⾯这些内容可能都会,下⾯在此基础上再复杂⼀点。
假如像上⾯SQL中的enabled = 1我想使⽤参数⽅式传值,也就是写成 enabled = #{enabled},如果你没有遇到过类似这种需求,可能不明⽩为什么要这么写,举个例⼦,要实现⼀种动态查询,可以在前台通过配置 SQL,提供⼀些查询条件就能实现⼀个查询的功能(为了安全,这些配置肯定是开发或者实施做的,不可能让⽤户直接操作数据库)。
针对这个功能,使⽤ MyBatis 实现起来相当容易。
配置 SQL 肯定要执⾏,⽤上⾯讲的这种⽅式肯定可以执⾏ SQL,如何提供参数呢?参数就是enabled = #{enabled}中的#{enabled}部分。
如果再多⼀些条件,⼀个配置好的 SQL 如下:select * from sysuserwhere enabled = #{enabled}and userName like concat('%',#{userName},'%')这种情况下,该怎么⽤ MyBatis 实现呢?⾸先 XML 中修改如下:<select id="executeSql" resultType="map">${sql}</select>接⼝中的⽅法修改为:List<Map> executeSql(Map map);然后调⽤⽅法:Map map = new HashMap();//这⾥的 sql 对应 XML 中的 ${sql}map.put("sql", "select * from sysuser "+ " where enabled = #{enabled} "+ " and userName like concat('%',#{userName},'%')");//#{enabled}map.put("enabled", 1);//#{userName}map.put("userName", "admin");//接⼝⽅式调⽤List<Map> list = xxMapper.executeSql(map);//sqlSession⽅式调⽤sqlSession.selectList("executeSql", map);有了这个SQL之后,就可以将 enabled 和 userName 作为条件提供给⽤户。
Mybatis中的动态SQL语句解析

Mybatis中的动态SQL语句解析这篇⽂章主要介绍了Mybatis中的动态SQL语句解析,⽂中通过⽰例代码介绍的⾮常详细,对⼤家的学习或者⼯作具有⼀定的参考学习价值,需要的朋友可以参考下 Mybatis中配置SQL有两种⽅式,⼀种是利⽤xml ⽅式进⾏配置,⼀种是利⽤注解进⾏配置。
Mybatis使⽤注解配置SQL,但是由于配置功能受限,⽽且对于复杂的SQL⽽⾔可读性很差,所以很少使⽤。
Mybatis常⽤xml配置的⽅式,使⽤xml的⼏个简单的元素,便能完成动态SQL的功能,⼤量的判断都可以在mybaties的映射xml⾥⾯配置,以达到许多需要⼤量代码才能实现的功能,⼤⼤减少了代码量,体现了Mybatis的灵活、⾼度可配置性和维护性。
元素作⽤备注if判断语句单条件分⽀判断choose(when,otherwise)相当于Java中的switch和case语句多条件分⽀判断trim辅助元素,⽤于处理特定的SQL拼装问题⽤于处理SQL拼装的问题foreach循环语句在in语句等列表条件常⽤if元素 if元素是最常⽤的判断语句,相当于Java中国的 if 语句,它常常与test属性联合使⽤。
<select id="findRole1" parameterType="string" resultMap="roleResultMap">select role_no, role_name, note from t_role where 1=1<if test="roleName != null and roleName !=''">and role_name like concat('%', #{roleName}, '%')</if></select> 当参数roleName传递进映射器时,如果参数不为空,则采取构造对 roleName 的模糊查询,否则就不要去构造这个条件。
mysql 中的 sql执行流程

mysql 中的 sql执行流程Mysql 中的 SQL 执行流程概述•MySQL 是一款广泛使用的开源关系型数据库管理系统,它使用SQL 语言进行数据管理和操作。
•SQL 执行流程是指 MySQL 在执行 SQL 语句时的内部运行过程,包括解析 SQL 语句、优化执行计划、执行计划等多个步骤。
SQL 执行流程步骤1.解析 SQL 语句–MySQL 首先会对输入的 SQL 语句进行解析,判断语法的正确性和合法性。
–解析过程包括词法分析和语法分析,将 SQL 语句转换成抽象语法树(AST)表示。
2.语义分析–在语义分析阶段,MySQL 对解析得到的抽象语法树进行分析,并验证 SQL 语句是否符合语义规则。
–语义分析会检查表名、列名的存在性、权限等,并进行相应的错误提示或警告。
3.优化执行计划–在优化执行计划阶段,MySQL 会根据 SQL 语句的查询需求和数据库的特点,生成多个执行计划。
–MySQL 内部会使用优化器选择出最优的执行计划,以提高查询效率。
–优化过程包括索引选择、连接顺序优化、子查询优化等。
4.执行计划–在执行计划阶段,MySQL 会根据最优的执行计划,按照特定的流程执行 SQL 语句。
–MySQL 会使用存储引擎的接口,读取和写入数据。
存储引擎的作用•存储引擎是 MySQL 中负责底层数据存储和管理的模块,不同的存储引擎有不同的特点和适用场景。
•MySQL 支持多种存储引擎,如 InnoDB、MyISAM、Memory 等。
InnoDB 存储引擎•InnoDB 是 MySQL 中最常用和性能较好的存储引擎。
•InnoDB 支持事务和行级锁,具有高并发性和数据一致性。
MyISAM 存储引擎•MyISAM 是 MySQL 的另一个常用的存储引擎。
•MyISAM 不支持事务,但在读写比较均衡的场景下,有较好的性能。
Memory 存储引擎•Memory 存储引擎将数据存储在内存中,适用于一些读写频繁但数据不需要长期存储的场景。
MyBatis原理与执行流程

MyBatis原理与执⾏流程⾸先感谢尚硅⾕的⽼师讲解!Mybatis流程分四步:1. 返回创建SqlSessionFactory对象2. 返回SqlSession的实现类DefaultSqlSession对象3. 返回⼀个MapperProxy的代理对象4. 执⾏询流程。
第⼀步返回创建SqlSessionFactory对象SqlSessionFactoryBuilder().build(inputStream);如何得到配置⽂件的内容?创建解析器解析全局配置⽂件XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);得到全局配置⽂件的配置内容 , 解析每⼀个标签把详细信息保存在Configuration中//解析配置⽂件标签build(parser.parse());propertiesElement(root.evalNode("properties"));Properties settings = settingsAsProperties(root.evalNode("settings"));loadCustomVfs(settings);typeAliasesElement(root.evalNode("typeAliases"));pluginElement(root.evalNode("plugins"));objectFactoryElement(root.evalNode("objectFactory"));全局配置⽂件中有该属性可以解析mapper.xml⽂件也保存到Configuration中mappers><package name="dao"/></mappers>Mapper.xml中的每个元素解析出来保存到全局配置中将增删改查标签的每⼀个标签每⼀个属性也解析出来封装到⼀个MapperedStatement中⼀个MapperedStatement就代表⼀个增删改查标签的详细信息最后 return configuration;包括全局配置信息和mapper.xml映射⽂件的各种信息返回的configuration通过buildreturn new DefaultSqlSessionFactory(config);configuration中mapperRegistry属性保存的是代理类信息mappedStatement属性保存的是增删查改等标签内容总结:配置⽂件的信息解析保存到Configureation对象中返回包含Configureation的DefaultSqlSessionFactory第⼆步返回SqlSession的实现类DefaultSqlSession对象他⾥⾯包含了Executor(是⽤来增删改查的)和Configuration。
1条sql执行的完整过程

1条sql执行的完整过程当一条SQL语句被提交给数据库执行时,它需要经过多个步骤才能完成。
以下是SQL语句执行的完整过程:1. **解析(Parsing)**:* 查询首先被解析器解析。
解析器检查SQL语句的语法和结构,并创建一个解析树。
* 语法错误在这个阶段会被检测出来。
2. **预处理(Preprocessing)**:* 在预处理器中,解析器检查是否有任何语法错误,并确保所有的对象(如表和视图)都存在并且可以访问。
* 预处理器还会处理一些简单的查询重写,例如处理别名和子查询。
3. **优化(Optimization)**:* 在这个阶段,查询优化器会生成多个可能的执行计划,并选择一个最优的计划来执行查询。
* 优化器会考虑多种因素,如表的大小、索引的存在与否、数据的分布等,来决定最佳的执行策略。
4. **生成执行计划(Plan Generation)**:* 一旦选择了最优的执行计划,就会生成一个或多个执行计划。
这些计划描述了数据库如何实际执行查询。
5. **执行(Execution)**:* 在这个阶段,数据库引擎根据执行计划执行查询。
这可能涉及到读取数据、连接表、过滤记录等操作。
6. **返回结果(Result Returning)**:* 最后,查询的结果被返回给客户端。
这可能是一个表、一行数据、一个状态码等,具体取决于查询的类型和需求。
7. **后处理(Postprocessing)**:* 在某些情况下,可能还需要进行一些后处理步骤,例如处理事务或清理资源。
注意:不同的数据库系统可能会有不同的执行步骤或略有不同的执行顺序。
上述过程是一个通用的概述。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
MyBatis源码分析-SQL语句执行的完整流程MyBatis 是支持定制化SQL、存储过程以及高级映射的优秀的持久层框架。
MyBatis 避免了几乎所有的JDBC 代码和手动设置参数以及获取结果集。
MyBatis 可以对配置和原生Map 使用简单的XML 或注解,将接口和Java 的POJOs(Plain Old Java Objects,普通的Java对象)映射成数据库中的记录。
如何新建MyBatis源码工程请点击MyBatis源码分析-IDEA 新建MyBatis源码工程。
MyBatis框架主要完成的是以下2件事情:根据JDBC规范建立与数据库的连接。
通过反射打通Java对象与数据库参数交互之间相互转换的关系。
MyBatis框架是一种典型的交互式框架,先准备好交互的必要条件,然后构建一个交互的环境,在交互环境中划分会话,在会话中与数据库进行交互数据。
1 MyBatis主要的类Configuration MyBatis所有的配置信息都维持在Configuration对象之中。
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语句以及相应的参数信息以上几个类在SQL操作中都会涉及,在SQL操作中重点关注下SQL参数什么时候写入和结果集怎么转换为Java对象,这两个过程正好对应的类是PreparedStatementHandler和ResultSetHandler类。
(图片来自《深入理解mybatis原理》MyBatis的架构设计以及实例分析)2 SQL执行流程MyBatis主要设计目的还是为了让我们在执行SQL时对输入输出的数据的管理更加方便,所以方便的让我们写出SQL和方便的获取SQL的执行结果是MyBatis的核心竞争力。
下面就用一个例子来从源码角度看一下SQL的完整执行流程。
新建配置文件conf.xml:conf.xml首先建立数据表,这里就以user表为例:复制代码DROP TABLE IF EXISTS user;CREATE TABLE user (id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,name VARCHAR(32) NOT NULL,password VARCHAR(32) NOT NULL,email VARCHAR(32),phone VARCHAR(16),admin VARCHAR(16));复制代码然后新建与数据表对应的类User:User再新建usre表的配置文件:userMapper.xml最后新建测试类:复制代码/*** MyBatis测试类*/public class TestMain {public static void main(String[] args) throws IOException {String resouce = "conf.xml";InputStream is = Resources.getResourceAsStream(resouce);// 构建sqlSession工厂SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);// 获取sqlSessionSqlSession session = sqlSessionFactory.openSession();User user;try {/*** 第一种方式: 直接执行已映射的SQL 语句*/String statement = "erDao.getById";user = session.selectOne(statement, 1);System.out.println(user);}finally {session.close();}/*** 第二种方式: 执行更清晰和类型安全的代码// UserDao userDao = session.getMapper(UserDao.class);// user = userDao.getById(1);// System.out.println(user);}}复制代码由于我们分析的是SQL的执行流程,那就重点关注下user = session.selectOne(statement, 1); 这行代码~ 注意,传进去的参数是1。
session是DefaultSqlSession类型的,因为sqlSessionFactory默认生成的SqlSession是DefaultSqlSession类型。
selectOne()会调用selectList()。
复制代码// DefaultSqlSession类public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) {try {MappedStatement ms = configuration.getMappedStatement(statement);// CURD操作是交给Excetor去处理的return executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER);} catch (Exception e) {throw ExceptionFactory.wrapException("Error querying database. Cause: " + e, e);} finally {ErrorContext.instance().reset();}}复制代码在DefaultSqlSession.selectList中的各种CURD操作都是通多Executor进行的,这里executor的类型是CachingExecutor,接着跳转到其中的query方法中。
// CachingExecutor 类public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException { BoundSql boundSql = ms.getBoundSql(parameterObject); // 获取绑定的sql命令,比如"SELECT * FROM xxx"CacheKey key = createCacheKey(ms, parameterObject, rowBounds, boundSql);return query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);}getBoundSql为了获取绑定的sql命令,在创建完cacheKey之后,就进入到CachingExecutor 类中的另一个query方法中。
复制代码// CachingExecutor 类@Overridepublic <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {Cache cache = ms.getCache();if (cache != null) {flushCacheIfRequired(ms);if (ms.isUseCache() && resultHandler == null) {@SuppressWarnings("unchecked")List<E> list = (List<E>) tcm.getObject(cache, key);if (list == null) {list = delegate.<E> query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);tcm.putObject(cache, key, list); // issue #578 and #116}return list;}}return delegate.<E> query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);}复制代码这里真正执行query操作的是SimplyExecutor代理来完成的,接着就进入到了SimplyExecutor的父类BaseExecutor的query方法中。
复制代码// SimplyExecutor的父类BaseExecutor类@SuppressWarnings("unchecked")@Overridepublic <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {ErrorContext.instance().resource(ms.getResource()).activity("executing a query").object(ms.getId());if (closed) {throw new ExecutorException("Executor was closed.");}if (queryStack == 0 && ms.isFlushCacheRequired()) {clearLocalCache();}List<E> list;try {queryStack++;/*** localCache是一级缓存,如果找不到就调用queryFromDatabase从数据库中查找*/list = resultHandler == null ? (List<E>) localCache.getObject(key) : null;if (list != null) {handleLocallyCachedOutputParameters(ms, key, parameter, boundSql);} else {list = queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql);}} finally {queryStack--;}if (queryStack == 0) {for (DeferredLoad deferredLoad : deferredLoads) {// issue #601deferredLoads.clear();if (configuration.getLocalCacheScope() == LocalCacheScope.STATEMENT) {// issue #482clearLocalCache();}}return list;}复制代码因为是第一次SQL查询操作,所以会调用queryFromDatabase方法来执行查询。