MyBatis篇

大家好我是小明,今天学习mybatis


文章目录

  • [1. MyBatis执行流程](#1. MyBatis执行流程)
  • [2. MyBatis是否支持延迟加载](#2. MyBatis是否支持延迟加载)
  • [3. MyBtis的一级缓存,二级缓存](#3. MyBtis的一级缓存,二级缓存)
  • [🎯4. MyBatis 中 #{} 和 {} 的核心区别](#{} 和 {} 的核心区别)

1. MyBatis执行流程

大体流程

这个更详细:

讲解一下这个流程:

初始化阶段:服务器启动时会加载mybatis-config.xml文件(现在boot项目也可以使用applicationyml文件来配置数据信息),然后构建会话工厂sqlSessionFactroy

运行时阶段:会话工厂sqlSessionFactroy会创建一个SqlSession对象(相当于「数据库会话」,非线程安全,每次请求 / 方法调用都要新建),SqlSession 封装了数据库连接和执行 SQL 的方法,把对象交给Executor执行器来操作数据库,Executor接口的执行方法中有一个MappedStatement参数类型对象记录映射信息(resultType,还有一些入参数).

MyBatis执行流程

  • 读取 MyBatis 配置文件:mybatis-config.xml 加载运行环境和映射文件
  • 构造会话工厂 SqlSessionFactory
  • 会话工厂创建 SqlSession 对象(包含了执行 SQL 语句的所有方法)
  • 操作数据库的接口,Executor 执行器,同时负责查询缓存的维护
  • Executor 接口的执行方法中有一个 MappedStatement 类型的参数,封装了映射信息
  • 输入参数映射
  • 输出结果映射

2. MyBatis是否支持延迟加载

答:支持但是默认是没有开启

什么叫延迟加载??

举一个例子:

即:按需加载

来看一个代码

这个代码是执行selectById方法之后会立马执行,图片红色方框中的findByUid方法将该用户的订单全部查询出来。

可以修改一个属性fetchType=lazy开启延迟加载。

我们来看一个案例

我们注释掉一段代码看看

看这里就是不查询第二条sql只查询第一条,只有我们需要的时候在查询。

这个fatchtype属性也可以修改成全局的。

延迟加载的底层原理


3. MyBtis的一级缓存,二级缓存

  1. 一级缓存(本地缓存)

默认是开启的

作用范围: SqlSession 级别,即同一个数据库会话内有效。

生命周期: 和 SqlSession 绑定,SqlSession 关闭或提交 / 回滚事务时,一级缓存就会被清空。

核心原理:

  • 第一次执行 userMapper.selectById(1) 时,MyBatis 会去数据库查询,同时把结果存入当前 SqlSession 的一级缓存中。
  • 同一个 SqlSession 内再次执行相同的查询,会直接从缓存中取结果,不再访问数据库。

触发清空缓存的场景:

  • 执行 update/delete/insert 等写操作时,MyBatis 会自动清空当前 SqlSession 的一级缓存,避免脏数据。
  • 调用 sqlSession.clearCache() 手动清空。
  • SqlSession 关闭或事务提交 / 回滚。
    例子:

    2. 二级缓存

默认是关闭的

在配置文件中添加配置cacheEnabled=true开启

作用范围: Mapper 级别(namespace 级别),同一个 namespace(是存储SqlSession 的hashMap) 下的所有 SqlSession 共享缓存。

生命周期: 和 SqlSessionFactory 绑定,只要工厂不关闭,缓存就会一直存在(可配置过期时间)

核心原理:

  • 第一次查询后,结果会先存入一级缓存;当 SqlSession 关闭时,一级缓存的内容会被同步到二级缓存。
  • 其他 SqlSession 执行相同 namespace 下的相同查询时,会直接从二级缓存中取结果。

注意事项:

  • 只有 SqlSession 关闭或提交后,一级缓存的数据才会进入二级缓存。
  • 执行写操作(update/delete/insert)时,会清空当前 namespace 下的二级缓存。
  • 缓存的对象需要实现 Serializable 接口,因为二级缓存可能会被序列化到磁盘或跨进程共享。

例子

正常来说,会执行两次sql,开启二级缓存后sql会执行一次会话关闭后,数据从一级缓存到二级缓存,第二次会从二级缓存里面拿数据。


🎯4. MyBatis 中 #{} 和 ${} 的核心区别

#{name}(预编译占位符)

原理: MyBatis 会把 #{name} 解析成 JDBC 的 ? 占位符,在执行 SQL 前通过 PreparedStatement 预编译,再把参数值安全地设置到占位符中。

安全性: 可以有效防止 SQL 注入,因为参数值是通过 setXxx() 方法设置的。

${name}(字符串直接替换)

原理: MyBatis 会直接把 ${name} 替换成参数的原始字符串,相当于字符串拼接,不会经过预编译处理。

安全性: 存在 SQL 注入风险,因为参数会直接嵌入 SQL 语句中。


好了今天就到这里

相关推荐
李广坤15 小时前
MySQL 大表字段变更实践(改名 + 改类型 + 改长度)
数据库
爱可生开源社区2 天前
2026 年,优秀的 DBA 需要具备哪些素质?
数据库·人工智能·dba
随逸1772 天前
《从零搭建NestJS项目》
数据库·typescript
加号32 天前
windows系统下mysql多源数据库同步部署
数据库·windows·mysql
シ風箏2 天前
MySQL【部署 04】Docker部署 MySQL8.0.32 版本(网盘镜像及启动命令分享)
数据库·mysql·docker
李慕婉学姐2 天前
Springboot智慧社区系统设计与开发6n99s526(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
数据库·spring boot·后端
百锦再3 天前
Django实现接口token检测的实现方案
数据库·python·django·sqlite·flask·fastapi·pip
tryCbest3 天前
数据库SQL学习
数据库·sql
jnrjian3 天前
ORA-01017 查找机器名 用户名 以及library cache lock 参数含义
数据库·oracle
十月南城3 天前
数据湖技术对比——Iceberg、Hudi、Delta的表格格式与维护策略
大数据·数据库·数据仓库·hive·hadoop·spark