MyBatis 面试专题

MyBatis 面试专题
- 基础概念
- MyBatis中的工作原理
- MyBatis 与 Hibernate 的区别?
- #{} 和 ${} 的区别?
- MyBatis 的核心组件有哪些?
- 映射与配置
- 如何传递多个参数?
- ResultMap 的作用是什么?
- 动态 SQL 常用标签有哪些?
- 如何复用 SQL 片段?
- 当实体中的属性和表中的字段不一致的情况下怎么办?
- 高级特性
- 一级缓存与二级缓存的区别?
- MyBatis中如何实现缓存的扩展
- 如何实现延迟加载(懒加载)?
- MyBatis 插件(Plugin)原理?
- 分页插件的实现原理?
- 关联查询
- 一对一查询如何配置?
- 一对多查询如何配置?
- 嵌套查询 vs 嵌套结果的区别?
- 事务与性能
- MyBatis 如何管理事务?
- 如何执行批量操作?
- 常见问题排查
- 如何防止SQL注入
- Mapper 接口如何绑定到 XML?
- 如何获取自动生成的主键?
- 遇到 BindingException 可能的原因?
- 扩展与集成
- 如何与 Spring 集成?
- MyBatis 如何整合分布式缓存(如 Redis)?
基础概念
MyBatis中的工作原理
- 系统启动的时候会加载解析全局配置文件和对应映射文件。加载解析的相关信息存储在
Configuration对象@Test public void test1() throws Exception{ // 1.获取配置文件 InputStream in = Resources.getResourceAsStream("mybatis-config.xml"); // 2.加载解析配置文件并获取SqlSessionFactory对象 // SqlSessionFactory 的实例我们没有通过 DefaultSqlSessionFactory直接来获取 // 而是通过一个Builder对象来建造的 // SqlSessionFactory 生产 SqlSession 对象的 SqlSessionFactory 应该是单例 // 全局配置文件和映射文件 也只需要在 系统启动的时候完成加载操作 // 通过建造者模式来 构建复杂的对象 1.完成配置文件的加载解析 2.完成 SqlSessionFactory的创建 SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in); // 3.根据SqlSessionFactory对象获取SqlSession对象 SqlSession sqlSession = factory.openSession(); // 4.通过SqlSession中提供的 API方法来操作数据库 List<User> list = sqlSession.selectList("com.boge.mapper.UserMapper.selectUserList"); // 获取接口的代码对象 得到的其实是 通过JDBC代理模式获取的一个代理对象 // UserMapper mapper = sqlSession.getMapper(UserMapper.class); //List<User> list = mapper.selectUserList(); System.out.println("list.size() = " + list.size()); // 5.关闭会话 sqlSession.close(); // 关闭session 清空一级缓存 } - SqlSessionFactory: new DefaultSqlSessionFactory 全局配置文件的加载解析【Configuration】,映射文件的加载解析【Configuration,MappedStatement】
- SqlSession:new DefaultSqlSession,创建相关的事务工厂,完成Executor的创建,已经二级缓存CachingExecutor的装饰,同时完成了插件逻辑的植入。
- selectOne(); 二级缓存 -> 一级缓存 --> 数据库插入。
- SqlSession.getMapper()。

源码结构

MyBatis 与 Hibernate 的区别?
- MyBatis:半自动 ORM,需手动编写 SQL,灵活性高,适合复杂查询或对 SQL 优化有要求的场景。
- Hibernate:全自动 ORM,通过 HQL 或 Criteria API 操作对象,适合快速开发简单 CRUD,但对复杂 SQL 支持较弱。
#{} 和 ${} 的区别?
- #{}:预编译处理(占位符 ?),防止 SQL 注入,自动处理类型转换。
- ${}:字符串替换(直接拼接 SQL),需手动防注入,常用于动态表名、列名等非参数场景。
MyBatis 的核心组件有哪些?
SqlSessionFactory(会话工厂)、SqlSession(会话)、Mapper 接口、Executor(执行器)、MappedStatement(SQL 映射)。
映射与配置
如何传递多个参数?
使用 @Param 注解标注参数名,或通过 POJO 对象、Map 封装参数。
ResultMap 的作用是什么?
解决数据库列名与 Java 对象属性名不一致的问题,支持复杂关联映射(一对一、一对多)。
动态 SQL 常用标签有哪些?
<if>、<choose>/<when>/<otherwise>、<foreach>、<where>、<set>、<trim>
<select id="queryPageAllEmployee" resultType="com.todaytech.salary.basicInfo.model.vo.EmployeeVO">SELECT * FROM (SELECT un.agency_name AS unit_name,un.mof_dep_code, d.dept_name AS dept_name, eunf.zj_tied_date, eunf.xs_retire_expert, ef.* ,eunf.stopsignFROM zz_employeefix efLEFT JOIN zz_employeeunfix eunf ON ef.emp_id = eunf.emp_idINNER JOIN sys_agency un ON ef.unit_id = un.idINNER JOIN zz_department d ON (ef.unit_id = d.unit_id AND ef.dept_id = d.dept_id)<choose><when test="salaryAgencyType != null and salaryAgencyType != ''">WHERE (ef.salary_agency_type = #{salaryAgencyType}<if test="childrenAgencyIds != null and childrenAgencyIds.size() > 0 ">OR ef.unit_id IN <foreach collection="childrenAgencyIds" item="item" open="(" separator="," close=")"> #{item} </foreach></if>)</when><otherwise><if test="childrenAgencyIds != null and childrenAgencyIds.size() > 0 ">WHERE ef.unit_id IN <foreach collection="childrenAgencyIds" item="item" open="(" separator="," close=")"> #{item} </foreach></if></otherwise></choose> ) em${ew.customSqlSegment}ORDER BY emp_id DESC,emp_modified DESC</select>
如何复用 SQL 片段?
使用 <sql> 定义片段,通过 <include> 引用。
<sql id="getChildNotDeptSql">select orgclosure_id as id from sys_agency_relation where orgclosure_pid=#{agencyId}
</sql>
<select id="queryUnitIds" resultType="java.lang.Integer">select * from (<include refid="com.todaytech.vue.mapper.SysAgencyMapper.getChildNotDeptSql"><property name="agencyId" value="#{agencyId}"/></include> ) ug
</select>
当实体中的属性和表中的字段不一致的情况下怎么办?
- 我们可以在对应的SQL语句中通过
别名的方式来解决这个问题。 - 我们通过自定义
resultMap标签来设置属性和字段的映射关系
高级特性
一级缓存与二级缓存的区别?
- 缓存的作用:减低数据源的访问频率。从而提高数据源的处理能力。或者提高服务器的响应速度。
- 一级缓存:基于 SqlSession 级别,默认开启,会话结束或执行更新操作(增删改)时失效。
- 二级缓存:基于 namespace(Mapper 级别),需手动开启,跨会话共享,通过序列化机制实现。
- 为什么会先走二级缓存再走一级缓存?
- 二级缓存的作用域是SqlSessionFactory级别-90%找到。
- 一级缓存是SqlSession级别的-5%找到。
MyBatis中如何实现缓存的扩展
- 创建
Cache接口的实现。重写getObject和putObject方法。 - 怎么让我们自定义的实现:在
cache标签中通过type属性关联我们自定义的Cache接口的实现。
如何实现延迟加载(懒加载)?
在 <association> 或 <collection> 中配置 fetchType="lazy",需全局启用 lazyLoadingEnabled=true
- 全局懒加载
<settings><setting name="lazyLoadingEnabled" value="true"/><setting name="aggressiveLazyLoading" value="false"/> </settings> - 局部懒加载
<resultMap id="userResultMap" type="User"><id property="id" column="id"/><result property="username" column="username"/><collection property="orders" javaType="ArrayList" ofType="Order" select="selectOrdersByUserId" column="id" fetchType="lazy"/> </resultMap><select id="selectUserById" resultMap="userResultMap">SELECT * FROM user WHERE id = #{id} </select><select id="selectOrdersByUserId" resultType="Order">SELECT * FROM orders WHERE user_id = #{userId} </select>
MyBatis 插件(Plugin)原理?
基于动态代理,拦截 Executor、StatementHandler、ParameterHandler、ResultSetHandler 的核心方法,实现自定义逻辑(如分页、性能监控)。
分页插件的实现原理?
拦截待执行 SQL,重写为分页查询(如 MySQL 的 LIMIT),并查询总数。
关联查询
一对一查询如何配置?
使用 <association> 标签,通过 property 指定对象属性,resultMap 或 column 映射关联结果。
<resultMap id="UserResultMap" type="User"><id property="id" column="id" /><result property="name" column="name" /><association property="address" javaType="Address"><id property="id" column="address_id" /><result property="city" column="city" /><result property="state" column="state" /></association>
</resultMap>
<select id="selectUserWithAddress" resultMap="UserResultMap">SELECT u.id, u.name, a.id as address_id, a.city, a.stateFROM User uLEFT JOIN Address a ON u.address_id = a.id
</select>
一对多查询如何配置?
使用 <collection> 标签,类似一对一,但映射对象为集合类型。
<resultMap id="UserResultMap" type="User"><id property="id" column="id" /><result property="name" column="name" /><collection property="orders" ofType="Order"><id property="id" column="order_id" /><result property="orderDate" column="order_date" /></collection>
</resultMap>
<select id="selectUserWithOrders" resultMap="UserResultMap">SELECT u.id, u.name, o.id as order_id, o.order_date FROM User uLEFT JOIN Order o ON u.id = o.user_id
</select>
嵌套查询 vs 嵌套结果的区别?
- 嵌套查询:执行多次 SQL(可能引发 N+1 问题)。
- 嵌套结果:单次复杂查询,通过 ResultMap 映射结果。
事务与性能
MyBatis 如何管理事务?
默认使用 JDBC 事务(通过 Connection 的提交/回滚),集成 Spring 后由 Spring 统一管理。
如何执行批量操作?
使用 SqlSession 的 BatchExecutor,或在动态 SQL 中使用 <foreach> 拼接批量语句。
常见问题排查
如何防止SQL注入
-
优先使用 #{} 占位符
SELECT * FROM users WHERE username = #{username} -
避免直接使用 ${} 拼接字符串
SELECT * FROM users WHERE username = '${username}' -
安全使用动态 SQL 标签
<select id="findUsers" parameterType="map">SELECT * FROM users<where><if test="username != null">AND username = #{username}</if></where> </select> -
强制校验 ${} 的使用场景
- 必须使用时(如动态表名、排序字段):
- 白名单过滤:仅允许预定义的合法值(如 orderBy 参数只接受 id, name)。
- 避免用户输入直接控制:如从下拉菜单选择排序字段,而非自由输入。
- 必须使用时(如动态表名、排序字段):
Mapper 接口如何绑定到 XML?
通过 namespace 指定接口全限定名,方法名与 XML 中的 id 一致。
即:Java(包名+类名)=xml(namespace+id)
如何获取自动生成的主键?
配置 useGeneratedKeys="true" 和 keyProperty(如返回自增 ID 到对象的 id 属性)。
<insert id="insertUser" useGeneratedKeys="true" keyProperty="id">INSERT INTO user (name, email)VALUES (#{name}, #{email})
</insert>
遇到 BindingException 可能的原因?
Mapper 接口未扫描到、XML 中 id 与接口方法名不匹配、namespace配置错误。
扩展与集成
如何与 Spring 集成?
使用 mybatis-spring 库,配置 SqlSessionFactoryBean 和 MapperScannerConfigurer 扫描 Mapper 接口。
MyBatis 如何整合分布式缓存(如 Redis)?
自定义 Cache 接口实现类,替换默认的 PerpetualCache。
相关文章:
MyBatis 面试专题
MyBatis 面试专题 基础概念MyBatis中的工作原理MyBatis 与 Hibernate 的区别?#{} 和 ${} 的区别?MyBatis 的核心组件有哪些? 映射与配置如何传递多个参数?ResultMap 的作用是什么?动态 SQL 常用标签有哪些?…...
Animation - AI Controller控制SKM_Manny的一些问题
一些学习笔记归档; 在UE5中,使用新的小白人骨骼:SKM_Manny,会跟UE4中的小白人有一些差别; 比如在用AI Controller控制使用该骨骼(配置默认的ABP_Manny Animation BP)角色的时候,需要…...
安科瑞新能源防逆流解决方案:守护电网安全,赋能绿色能源利用
随着光伏、储能等新能源在用户侧的快速普及,如何避免电力逆流对电网造成冲击,成为行业关注的焦点。安科瑞凭借技术实力与丰富的产品矩阵,推出多场景新能源防逆流解决方案,以智能化手段助力用户实现安全、经济的能源管理࿰…...
filebeat和logstash区别
Filebeat 角色: 轻量级日志收集器。 功能: 从指定的日志文件中读取日志数据。 可以从多个源(如文件、系统日志、容器日志等)收集日志。 将收集到的日志数据传输到 Logstash、Elasticsearch 或其他支持的输出端点。 性能: 由于是轻量级的,File…...
【一起学Rust | Tauri2.0框架】基于 Rust 与 Tauri 2.0 框架实现全局状态管理
前言 在现代应用程序开发中,状态管理是构建复杂且可维护应用的关键。随着应用程序规模的增长,组件之间共享和同步状态变得越来越具有挑战性。如果处理不当,状态管理可能会导致代码混乱、难以调试,并最终影响应用程序的性能和可扩…...
扩散模型算法实战——三维重建的应用
✨个人主页欢迎您的访问 ✨期待您的三连 ✨ ✨个人主页欢迎您的访问 ✨期待您的三连 ✨ ✨个人主页欢迎您的访问 ✨期待您的三连✨ 1. 引言 三维重建是计算机视觉和图形学中的一个重要研究方向,旨在从二维图像或其他传感器数据中恢复…...
社群经济4.0时代:开源链动模式与AI技术驱动的电商生态重构
摘要:在Web3.0技术浪潮与私域流量红利的双重驱动下,电商行业正经历从"流量收割"到"用户深耕"的范式转变。本文基于社群经济理论框架,结合"开源链动21模式"、AI智能名片、S2B2C商城小程序源码等创新工具&#x…...
【Linux系统】进程等待:告别僵尸进程深入理解Linux进程同步的核心密码
Linux系列 文章目录 Linux系列前言一、进程等待的核心目的二、进程等待的实现方式2.1 wait()函数2.2 waitpid()函数 总结 前言 在Linux系统中,进程等待(Process Waiting)是多进程编程中的核心机制,指父进程…...
根据文件名称查询文件所在位置
在 Linux 中,根据文件名称查询文件所在位置主要通过命令行工具实现,以下是几种常用方法: --- ### **1. 使用 find 命令(最灵活)** find 命令可以递归搜索指定目录下的文件,支持按名称、类型、时间等条件过…...
六十天前端强化训练之第二十五天之组件生命周期大师级详解(Vue3 Composition API 版)
欢迎来到编程星辰海的博客讲解 看完可以给一个免费的三连吗,谢谢大佬! 目录 一、生命周期核心知识 1.1 生命周期全景图 1.2 生命周期钩子详解 1.2.1 初始化阶段 1.2.2 挂载阶段 1.2.3 更新阶段 1.2.4 卸载阶段 1.3 生命周期执行顺序 1.4 父子组…...
Pytorch使用手册(专题五十)—自定义运算符
1. PyTorch 自定义运算符 PyTorch 提供了一个庞大的运算符库,这些运算符可以对张量进行操作(例如 torch.add、torch.sum 等)。然而,您可能希望向 PyTorch 引入一个新的自定义操作,并使其能够与诸如 torch.compile、autograd 和 torch.vmap 等子系统协同工作。为此,您必须…...
springboot整合mybatis-plus(保姆教学) 及搭建项目
一、Spring整合MyBatis (1)将MyBatis的DataSource交给Spring IoC容器创建并管理,使用第三方数据库连接池(Druid,C3P0等)代替MyBatis内置的数据库连接池 (2)将MyBatis的SqlSessionFactory交给Spring IoC容器创建并管理,使用spring-mybatis整…...
VSCode创建VUE项目(三)使用axios调用后台服务
1. 安装axios,执行命令 npm install axios 2. 在 main.ts 中引入并全局挂载 Axios 实例 修改后的 代码(也可以单独建一个页面处理Axios相关信息等,然后全局进行挂载) import { createApp } from vue import App from ./App.vue import rou…...
JVM常用垃圾回收器
Serial 和Serial Old收集器 Serial 系列的垃圾收集器采用了简单高效、资源消耗最少、单线程收集的设计思路。 简单高效:由于硬件资源有限,垃圾回收器需要设计得简单高效,以减少系统资源的占用。Serial 系列的垃圾收集器实现简单,…...
车辆模型——运动学模型
文章目录 约束及系统移动机器人运动学模型(Kinematic Model)自行车模型含有加速度 a a a 的自行车模型系统偏差模型 在机器人的研究领域中,移动机器人的系统建模与分析是极为关键的基础环节,本文以非完整约束的轮式移动机器人为研…...
EJS缓存解决多页面相同闪动问题
基于 EJS 的模板引擎特性及其缓存机制,以下是关于缓存相同模块的详细解答: 一、EJS 缓存机制的核心能力 模板编译缓存 EJS 默认会将编译后的模板函数缓存在内存中,当相同模板文件被多次渲染时,会直接复用已编译的模板函数&#x…...
<details>和<summary>标签的用途,如何使用它们实现可折叠内容
大白话和标签的用途,如何使用它们实现可折叠内容 <details> 和 <summary> 标签用途 <details> 和 <summary> 标签是 HTML 里的实用标签,二者配合能创建出可折叠内容。 <details> 标签就像是一个容器,能把那…...
HUGO介绍、安装、以及使用
HUGO官方网站,文章内容的简介大部分来自官网的翻译,官网是纯英文描述,英语好的可以前往官方网站,博主在这里简介中简单翻译处理包括一些链接的引用,主要是讲解一下如何安装和使用。 这里再粘贴一个三方网站opendocs.i…...
【STM32实物】基于STM32的太阳能充电宝设计
基于STM32的太阳能充电宝设计 演示视频: 基于STM32的太阳能充电宝设计 硬件组成: 系统硬件包括主控 STM32F103C8T6、0.96 OLED 显示屏、蜂鸣器、电源自锁开关、温度传感器 DS18B20、继电器、5 V DC 升压模块 、TB4056、18650锂电池、9 V太阳能板、稳压降压 5 V三极管。 功能…...
【Netty】长连接与短连接的不同实现
长连接与短连接的不同实现 配置层面 // 长连接配置 bootstrap.option(ChannelOption.SO_KEEPALIVE, true) // 启用 TCP keepalive.option(ChannelOption.TCP_NODELAY, true); // 禁用 Nagle 算法// 短连接不需要这些配置心跳机制 // 长连接需要心跳 pipeline.addLast(new Idl…...
安装 OpenSSL 1.1.1 的完整脚本适用于 Ubuntu 22.04 系统
#!/bin/bash # 更新系统包 sudo apt-get update # 安装编译工具和依赖库 sudo apt-get install -y build-essential checkinstall zlib1g-dev # 下载 OpenSSL 1.1.1 源码 wget https://www.openssl.org/source/openssl-1.1.1.tar.gz # 检查下载是否成功 if [ $? -ne 0 ]; …...
24-智慧旅游系统(协同过滤算法)
介绍 技术: 基于 B/S 架构 SpringBootMySQLLayuivue 环境: Idea mysql maven jdk1.8 管理端功能 管理端主要用于对系统内的各类旅游资源进行管理,包括用户信息、旅游路线、车票、景点、酒店、美食、论坛等内容。具体功能如下: …...
Vue 中的日期格式化实践:从原生 Date 到可视化展示!!!
📅 Vue 中的日期格式化实践:从原生 Date 到可视化展示 🚀 在数据可视化场景中,日期时间的格式化显示是一个高频需求。本文将以一个邀请码关系树组件为例,深入解析 Vue 中日期格式化的 核心方法、性能优化 和 最佳实践…...
2025年使用Scrapy和Playwright解决网页抓取挑战的方案
0. 引言 随着互联网技术的发展,网页内容呈现方式越来越复杂,大量网站使用JavaScript动态渲染内容,这给传统的网络爬虫带来了巨大挑战。在2025年的网络爬虫领域,Scrapy和Playwright的结合为我们提供了一个强大的解决方案ÿ…...
可靠消息投递demo
以下是一个基于 Spring Boot RocketMQ 的完整分布式事务实战 Demo,包含事务消息、本地事务、自动重试、死信队列(DLQ) 等核心机制。代码已充分注释,可直接运行。 一、项目结构 src/main/java ├── com.example.rocketmq │ …...
阻止 Mac 在运行任务时进入休眠状态
掌握Caffeinate命令:让您的 Mac 保持清醒以完成关键任务 开发人员经常发现自己在 Mac 上运行持续时间较长的进程。无论是大量文件上传、广泛的数据分析脚本,还是复杂的构建过程,我们最不希望的就是我们的机器在任务中途进入睡眠状态。输入 c…...
Copilot提示词库用法:调整自己想要的,记住常用的,分享该共用的
不论你是 Microsoft 365 Copilot 的新用户还是熟练运用的老鸟,不论你是使用copilot chat,还是在office365中使用copilot,copilot提示词库都将帮助你充分使用copilot这一划时代的产品。它不仅可以帮助你记住日常工作中常用的prompt提示词&…...
Python实战(3)-数据库操作
前面说过,可用的SQL数据库引擎有很多,它们都有相应的Python模块。这些数据库引擎大都作为服务器程序运行,连安装都需要有管理员权限。为降低Python DB API的使用门槛,我选择了一个名为SQLite的小型数据库引擎。它不需要作为独立的…...
LeetCode 160 Intersection Of Two Linked Lists 相交链表 Java
题目:找到两个相交列表的起始点,如图c1开始为A和B两个链表的相交点 举例1:8为两个链表的相交点。 注意:相交不止是数值上的相同。 举例2:2为相交点 举例3:没有相交点 解题思路: 相交证明最后一…...
AI Agent中的MCP详解
一、协议定义与核心价值 MCP(Model Context Protocol,模型上下文协议)是由Anthropic公司于2024年11月推出的开放标准协议,其核心目标是通过建立统一接口规范,解决AI模型与外部系统集成效率低下的行业痛点。该协议通过标准化通信机制,使大型语言模型(LLM)能够无缝对接数…...
