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 语句中。


好了今天就到这里

相关推荐
一直都在5722 小时前
Spring3整合MyBatis实现增删改查操作
前端·vue.js·mybatis
TDengine (老段)2 小时前
TDengine R 语言连接器进阶指南
大数据·开发语言·数据库·r语言·时序数据库·tdengine·涛思数据
不会kao代码的小王2 小时前
深信服超融合 HCI 核心技术解析:aSV、aSAN 与 aNET 的协同架构
运维·服务器·网络·数据库·github
Maggie_ssss_supp2 小时前
Linux-MySQL数据备份与恢复
数据库·mysql
DBA小马哥2 小时前
文档型数据库MongoDB迁移替换:金仓数据库跨地域同步方案解析
数据库·安全·dba
DBA小马哥2 小时前
制造业时序数据管理的演进:从传统数据库到时序数据库的转型之路
数据库·时序数据库·dba
结衣结衣.2 小时前
Redis中的string字符串介绍
数据库·redis·缓存
你才是臭弟弟2 小时前
实时数据库与时序数据库
数据库·时序数据库