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


好了今天就到这里

相关推荐
野犬寒鸦3 分钟前
从零起步学习并发编程 || 第六章:ReentrantLock与synchronized 的辨析及运用
java·服务器·数据库·后端·学习·算法
晚霞的不甘1 小时前
揭秘 CANN 内存管理:如何让大模型在小设备上“轻装上阵”?
前端·数据库·经验分享·flutter·3d
市场部需要一个软件开发岗位2 小时前
JAVA开发常见安全问题:纵向越权
java·数据库·安全
海奥华22 小时前
mysql索引
数据库·mysql
2601_949593652 小时前
深入解析CANN-acl应用层接口:构建高效的AI应用开发框架
数据库·人工智能
javachen__2 小时前
mysql新老项目版本选择
数据库·mysql
Dxy12393102163 小时前
MySQL如何高效查询表数据量:从基础到进阶的优化指南
数据库·mysql
Dying.Light3 小时前
MySQL相关问题
数据库·mysql
蜡笔小炘3 小时前
LVS -- 利用防火墙标签(FireWall Mark)解决轮询错误
服务器·数据库·lvs
韩立学长3 小时前
基于Springboot泉州旅游攻略平台d5h5zz02(程序、源码、数据库、调试部署方案及开发环境)系统界面展示及获取方式置于文档末尾,可供参考。
数据库·spring boot·旅游