当前位置: 首页 > news >正文

【MyBatis保姆级教程下】万字XML进阶实战:配置指南与深度解析


目录

1.前言

2.正文

2.1XML文件配置

2.1.1标准框架

2.1.2MybatisX插件

2.1.4基础操作

2.1.4.1查

2.1.4.2增

2.1.4.3改

2.1.4.4删

2.1.3常见报错及解决方案

🚨 2.1.3.1配置文件对应问题

🔍 2.1.3.2字段映射问题

⚙️ 2.1.3.3参数绑定问题

📜 2.1.3.4配置文件语法错误

2.1.4在线diff工具

2.2其他查询操作

2.2.1多表查询

2.2.2慢sql问题

3.小结


1.前言

哈喽大家好吖,今天距离上一次更新已经过了一段时间了,博主也终于从前日的忙碌到现在可以继续静下心创作博客。今天来给大家继续分享的是MyBatis,上一篇没看过的记得看一下哦。【MyBatis保姆级教程上】近万字从零开始手把手教你玩转数据库操作!https://blog.csdn.net/2301_81073317/article/details/148234380?spm=1001.2014.3001.5501

上篇中主要采用的是注解的方式实现数据库操作。今天博文主要包括了通过配置XML文件来实现基础数据库操作,常见报错,在线diff工具,以及其他查询操作讲解,话不多说正文开始。


插播一条消息~

发现一个系统化的人工智能学习平台,涵盖从基础理论到工业级项目实战(人脸识别/自动驾驶/GANs等),内容由浅入深结构清晰,特别适合想体系化提升AI开发能力的朋友,忍不住把干货分享给大家👉

人工智能教学网站https://www.captainbed.cn/scy/


2.正文

2.1XML文件配置

测试数据库:

-- 创建表[用户表]
DROP TABLE IF EXISTS user_info;
CREATE TABLE `user_info` (`id` INT ( 11 ) NOT NULL AUTO_INCREMENT,`username` VARCHAR ( 127 ) NOT NULL,`password` VARCHAR ( 127 ) NOT NULL,`age` TINYINT ( 4 ) NOT NULL,`gender` TINYINT ( 4 ) DEFAULT '0' COMMENT '1-男 2-女 0-默认',`phone` VARCHAR ( 15 ) DEFAULT NULL,`delete_flag` TINYINT ( 4 ) DEFAULT 0 COMMENT '0-正常, 1-删除',`create_time` DATETIME DEFAULT now(),`update_time` DATETIME DEFAULT now() ON UPDATE now(),PRIMARY KEY ( `id` ) 
) ENGINE = INNODB DEFAULT CHARSET = utf8mb4; 

插入数据:

-- 添加用户信息
INSERT INTO mybatis_test.user_info( username, `password`, age, gender, phone )
VALUES ( 'admin', 'admin', 18, 1, '18612340001' );
INSERT INTO mybatis_test.user_info( username, `password`, age, gender, phone )
VALUES ( 'zhangsan', 'zhangsan', 18, 1, '18612340002' );
INSERT INTO mybatis_test.user_info( username, `password`, age, gender, phone )
VALUES ( 'lisi', 'lisi', 18, 1, '18612340003' );
INSERT INTO mybatis_test.user_info( username, `password`, age, gender, phone )
VALUES ( 'wangwu', 'wangwu', 18, 1, '18612340004' );

2.1.1标准框架

上篇我们主要使用了注解进行简单映射。当SQL变得复杂(如动态SQL、结果集映射复杂对象)时,XML配置文件才是王道。它提供了更强大的表达能力和更好的可维护性。

在resources资源包下创建文本文件,记得加上后缀.xml,标准框架如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.mybatis.mapper.UserInfoMapperXML"></mapper>

1. XML声明

  • 作用:声明这是一个XML文档

2. 文档类型定义(DTD)

  • 作用:定义XML文档结构规则

  • 关键功能

    • 提供XML结构验证

    • 支持IDE智能提示和自动补全

    • 确保MyBatis正确解析XML配置

3. Mapper根元素

  • <mapper>:MyBatis XML配置的根元素,所有SQL操作都定义在其中

  • namespace属性(绝对核心!)

    • 作用:将XML文件与Java Mapper接口绑定

    • 值要求:必须是Mapper接口的全限定名(包名+类名)

    • 示例解析com.example.mybatis.mapper.UserInfoMapperXML 表示:

      • 包路径:com.example.mybatis.mapper

      • 接口名:UserInfoMapperXML

4. 内容区域

  • 此处是实际定义SQL操作的位置

  • 可包含的子元素:

    • <select>:查询操作

    • <insert>:插入操作

    • <update>:更新操作

    • <delete>:删除操作

    • <resultMap>:结果集映射配置

    • <sql>:可重用的SQL片段

    • <cache>:缓存配置

内容区域是我们详细讲的数据库操作部分。

2.1.2MybatisX插件

在正式编写代码前,安装对代码编写有用的开发插件:

MyBatisX 是一款由 MyBatis-Plus 团队开发的 IntelliJ IDEA 插件,专为提升 MyBatis 开发效率设计。它通过智能导航、代码生成、动态提示等功能,显著简化了 Mapper 接口与 XML 文件的开发流程。

官方文档:

MyBatisX官方文档https://baomidou.com/guides/mybatis-x/

在idea设置中找到插件选项,搜索MyBatisX下载并应用,记得重启idea。

核心功能亮点:

  1. 双向导航与跳转

    • 在 Mapper 接口方法与 XML SQL 定义之间一键跳转,通过小鸟图标(红色头巾标识接口,蓝色头巾标识 XML)实现无缝切换236。

    • 解决开发中频繁切换文件的问题,提升代码定位效率。

  2. 图形化代码生成器

    • 连接数据库后,右键表即可生成 Entity、Mapper 接口、XML 文件、Service 层代码48。

    • 支持多表批量生成,并可自定义包路径、注解(如 Lombok、Swagger)、文件位置等38。

    • 模板自定义:修改 domain.ftl 等模板文件,灵活适配项目规范(例如添加 Swagger 注解)48。

  3. JPA 风格方法名提示

    • 根据方法名自动生成 SQL 实现。例如:

      • findByUsername(String name) → 生成 SELECT * FROM user WHERE username = #{name}

      • updateStatusById(Long id, Integer status) → 生成更新语句28。

    • 输入方法名时自动提示字段,避免手写 SQL 错误。

  4. SQL 辅助工具

    • 智能补全:自动提示表名、字段名、SQL 关键字57。

    • 日志转 SQL:复制 MyBatis 日志中的参数占位符(如 ?),自动转换为完整可执行的 SQL 语句1。

    • XML 校验:实时检查 SQL 语法与映射配置的正确性5。

2.1.4基础操作

查询操作详解,剩下的操作思路大致相同。

2.1.4.1查

Mapper层:

@Mapper
public interface UserInfoMapperXML {List<UserInfo> selectAll();List<UserInfo> selectAll2();
}

 model层:

@Data
public class UserInfo {private Integer id;private String username;private String password;private Integer age;private Integer gender;private String phone;private Integer deleteFlag;private Date createTime;private Date updateTime;
}

层和层之间的关系:

 

在 MyBatis 中主要有三种解决方案解决查询操作。下面通过具体示例详细讲解每种查询实现方式:

1. SQL 别名映射(Alias Mapping)

核心思想:在 SQL 查询语句中直接使用 AS 关键字为字段起别名,使其与 Java 属性名匹配

<select id="selectAll" resultType="com.example.mybatis.model.UserInfo">SELECT id, username, `password`, age, gender, phone,delete_flag AS deleteFlag,  <!-- 数据库字段 → Java属性 -->create_time AS createTime,  <!-- 下划线转驼峰 -->update_time AS updateTime   <!-- 字段别名匹配属性名 -->FROM user_info
</select>

实现原理

  • MyBatis 会将查询结果的列名直接对应到返回类型的属性名

  • 使用 AS 将数据库的蛇形命名(delete_flag)转换为 Java 的驼峰命名(deleteFlag

优点

  • 简单直观,适合简单查询

  • 零配置,无需额外声明

缺点

  • SQL 语句冗长(特别是字段多时)

  • 复用性差(相同映射需重复编写)


2. ResultMap 显式映射

核心思想:通过 <resultMap> 标签明确定义数据库字段与 Java 属性的映射关系

<!-- 1. 声明结果映射 -->
<resultMap id="baseMap" type="com.example.mybatis.model.UserInfo"><!-- 主键字段映射 --><id property="id" column="id"/><!-- 普通字段映射 --><result property="username" column="username"/><result property="password" column="password"/><result property="age" column="age"/><!-- 处理命名不一致的字段 --><result property="deleteFlag" column="delete_flag"/><result property="createTime" column="create_time"/><result property="updateTime" column="update_time"/>
</resultMap><!-- 2. 使用结果映射 -->
<select id="selectAll2" resultMap="baseMap">SELECT * FROM user_info  <!-- 无需字段别名 -->
</select>

关键特性

  • <id>:用于主键字段,提升性能并支持对象识别

  • <result>:定义普通字段映射

  • property:Java 实体类属性名(驼峰式)

  • column:数据库字段名(蛇形命名)

优点

  • 映射关系清晰可见

  • 可复用(多个查询可引用同一个 <resultMap>

  • 支持复杂映射(嵌套对象、集合等)

缺点

  • 配置稍显繁琐(需额外声明映射关系)


3. 全局驼峰命名转换

核心思想:开启 MyBatis 全局配置,自动将蛇形命名转为驼峰命名

配置方式(二选一):

1. 在 .xml 中启用:

<configuration><settings><!-- 开启驼峰命名自动映射 --><setting name="mapUnderscoreToCamelCase" value="true"/></settings>
</configuration>

2. Spring Boot 配置(application.yml):

mybatis:configuration:map-underscore-to-camel-case: true

自动转换规则

数据库字段名Java 属性名转换说明
delete_flagdeleteFlag下划线后字母大写
create_timecreateTime去除下划线并驼峰化
update_timeupdateTime同上

优点

  • 零编码映射(无需别名/ResultMap)

  • 保持 SQL 简洁

  • 一劳永逸(全局生效)

缺点

  • 无法自定义特殊字段映射

  • 对非标准命名支持有限

2.1.4.2增

Mapper层:

Integer insertUser(UserInfo userInfo);Integer insertUser2(@Param("userInfo") UserInfo userInfo);

XML:

<insert id="insertUser">insert into user_info (username, `password`, age)values(#{username}, #{password}, #{age})</insert><insert id="insertUser2" useGeneratedKeys="true" keyProperty="userInfo.id">insert into user_info (username, `password`, age)values(#{userInfo.username}, #{userInfo.password}, #{userInfo.age})</insert>

测试代码:

@Testvoid insertUser() {UserInfo userInfo = new UserInfo();userInfo.setUsername("u6");userInfo.setPassword("p4444");userInfo.setAge(10);userInfoMapperXML.insertUser(userInfo);System.out.println(userInfo.getId());}@Testvoid insertUser2() {UserInfo userInfo = new UserInfo();userInfo.setUsername("u8");userInfo.setPassword("p6666");userInfo.setAge(13);Integer result = userInfoMapperXML.insertUser2(userInfo);System.out.println("影响行数: " + result + ",自增id: " + userInfo.getId());}

 方式1:直接对象参数(基础版)

  • 无前缀访问:直接使用 #{属性名} 访问对象的属性

  • MyBatis 处理流程

    1. 获取方法参数对象 userInfo

    2. 通过反射读取属性值

    3. 将值注入 SQL 占位符

方式2:@Param 注解参数(高级版)

属性作用值说明
useGeneratedKeys启用数据库自增主键支持true/false (默认false)
keyProperty指定回填到参数的属性路径对象.属性 (如 userInfo.id)
  • 带前缀访问:必须使用 #{参数名.属性} 格式

  • @Param 作用:为参数创建命名空间

2.1.4.3改

Mapper层:

Integer updateUser(String password, Integer age, Integer id);

XML:

<update id="updateUser">update user_info set password = #{password}, age = #{age}where id = #{id}</update>

测试代码:

@Testvoid updateUser() {userInfoMapperXML.updateUser("updatePassword", 66, 13);}

 运行截图:

2.1.4.4删

Mapper层:

Integer deleteUser(Integer id);

XML:

<delete id="deleteUser">delete from user_info where id = #{id}</delete>

测试代码:

@Testvoid deleteUser() {userInfoMapperXML.deleteUser(17);}

运行截图: 

2.1.3常见报错及解决方案

常见的有四种报错,这里一一讲解:


🚨 2.1.3.1配置文件对应问题

报错现象
Invalid bound statement (not found)
org.apache.ibatis.binding.BindingException

根本原因
Mapper 接口与 XML 文件绑定失败

排查步骤

  • namespace 与接口全限定名不匹配
  • XML 文件存放位置错误
  • MyBatis 未扫描到 XML
  • SQL 语句 id 与方法名不匹配

🔍 2.1.3.2字段映射问题

报错现象
Could not set property 'createTime'
查询结果部分字段为 null

排查步骤:

  • 未开启驼峰命名转换
  • ResultMap 配置错误
  • SQL 未返回必要字段 

⚙️ 2.1.3.3参数绑定问题

报错现象
Parameter 'xxx' not found
There is no getter for property named 'xxx'

典型场景

// Mapper接口
List<User> selectByAge(@Param("min") Integer minAge, Integer maxAge); // 缺少@Param// XML
<select id="selectByAge">SELECT * FROM user WHERE age BETWEEN #{min} AND #{maxAge} <!-- 参数名错误 -->
</select>

解决方案

  1. 单参数:可直接用 #{任意名}

  2. 多参数:必须用 @Param 注解

    List<User> selectByAge(@Param("min") Integer minAge,@Param("max") Integer maxAge
    );
  3. 对象参数

    <!-- 正确 -->
    #{user.age}<!-- 错误 -->
    #{age} 

📜 2.1.3.4配置文件语法错误

报错现象
Error parsing SQL Mapper Configuration
XML 文件加载失败

排查重点

  • 特殊符号未转义

  • 标签未闭合

  • YAML 缩进错误

2.1.4在线diff工具

在 MyBatis 开发中,XML 配置与 Java 接口的一致性检查是高频痛点(如 namespace 不匹配、id 重复或遗漏),而人工比对效率低且易出错。此时 在线 Diff 工具 成为关键辅助手段,它能快速定位配置差异,显著提升排障效率。

常见的在线diff工具推荐:

  1. Diffchecker
    支持文本、代码、图片、PDF、Excel等文件的对比,免费且功能强大,适合代码审查和文档核对

  2. DiffNow
    专为文本、XML和JSON文件设计,提供差异检测和报告生成功能,操作简单

  3. 无双工具
    免费在线文本diff工具,支持代码对比、翻译差异检测,界面友好且无需注册。

  4. Draftable
    专注于PDF和Word文件的比对,免费账户提供300+文档模板,适合团队协作。

  5. LineDiff
    简单的在线文本对比工具,适合快速查看行级差异。

优势:

痛点Diff 工具作用传统方式缺陷
id 与接口方法名不一致秒级定位不匹配项肉眼逐行比对,耗时长易遗漏
namespace 路径错误验证接口全路径与 XML 声明一致性手动复制粘贴路径易出错
多人协作冲突快速识别版本间配置差异Git 差异查看不直观

通过自动化工具替代人工校验,开发者可更专注业务逻辑实现,减少“配置一致性”问题带来的时间损耗。

2.2其他查询操作

测试表:

-- 创建文章表
DROP TABLE IF EXISTS article_info;CREATE TABLE article_info (id INT PRIMARY KEY auto_increment,title VARCHAR ( 100 ) NOT NULL,content TEXT NOT NULL,uid INT NOT NULL,delete_flag TINYINT ( 4 ) DEFAULT 0 COMMENT '0-正常, 1-删除',create_time DATETIME DEFAULT now(),update_time DATETIME DEFAULT now() 
) DEFAULT charset 'utf8mb4';-- 插入测试数据
INSERT INTO article_info ( title, content, uid ) VALUES ( 'Java', 'Java正文', 1 );

2.2.1多表查询

这里讲解多表查询仅以一种为例:

我们用到的俩个表是两个测试代码中的表:

  • 文章表(article_info):存储文章信息

  • 用户表(user_info):存储作者信息

需求:根据文章ID查询文章详情同时获取作者的用户名和年龄(需要跨表查询)

Mapper:

@Mapper
public interface ArticleInfoMapper {ArticleInfo selectArticleInfoById(Integer id);}

model:

@Data
public class ArticleInfo {// 文章字段private Integer id;private String title;private String content;private Integer uid;       // 作者ID(关联字段)private Integer deleteFlag;private Date createTime;private Date updateTime;// 用户字段(多表查询扩展)private String username;   // 作者姓名private Integer age;       // 作者年龄
}

设计:实体类包含跨表字段,MyBatis会自动映射同名属性 

XML:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.mybatis.mapper.ArticleInfoMapper"><select id="selectArticleInfoById" resultType="com.example.mybatis.model.ArticleInfo">selectta.*,tb.username,tb.agefrom article_info taleft join user_info tbon ta.uid = tb.idwhere ta.id = 1
<!--        多表查询--></select>
</mapper>

运行截图:

多表查询的三种实现方式对比:

方式适用场景性能影响
JOIN查询关联数据量小单次查询
嵌套查询关联数据量大N+1查询问题
子查询简单过滤条件可能影响性能

2.2.2慢sql问题

一、什么是慢SQL?

想象你在图书馆找书:

  • ✅ 快查询:有精准的索书号(索引),直接找到书

  • ❌ 慢查询:没有索引,只能一排排书架翻找(全表扫描)

慢SQL就是执行时间过长的数据库查询,就像在图书馆里花1小时找一本书。通常当查询超过100毫秒,就认为是慢SQL。

 二、哪些场景会出现慢SQL?(常见例子)

1. 全表扫描(最典型)

-- 没有索引的查询(像没有目录的书架)
SELECT * FROM users WHERE name = '小明';

➤ 现象:数据库扫描10万行才找到1条数据

2. 多表关联查询

-- 同时查3张表(像同时翻3本书找信息)
SELECT * 
FROM orders
JOIN users ON orders.user_id = users.id
JOIN products ON orders.product_id = products.id;

➤ 风险:数据量指数级增长(100订单×100用户×100商品=100万组合)

3. 模糊查询

-- 开头模糊查询(像查"*结尾是明的名字")
SELECT * FROM users WHERE name LIKE '%明';

4. 大数据量分页

-- 翻到第1000页(像从1000页的书里撕下最后10页)
SELECT * FROM products LIMIT 10000, 10;

三、为什么慢SQL很危险?

问题类型后果类比
阻塞其他操作整个系统变卡顿收银台排长队
消耗CPU资源服务器负载飙升引擎过热
磁盘IO过高硬件寿命缩短汽车频繁急刹车
用户体验差页面加载转圈时间长电梯反应慢

四、常见解决方案

✅ 方案1:创建索引

-- 给name字段加索引(像给书加目录)
CREATE INDEX idx_name ON users(name);-- 查询立刻变快
SELECT * FROM users WHERE name = '小明'; 

方案2:减少多表查询

/* 优化前(三表关联) */
SELECT products.*, users.name 
FROM orders
JOIN users ON orders.user_id = users.id
JOIN products ON orders.product_id = products.id;/* 优化后(拆成两次简单查询) */
-- 第一步:查订单信息
SELECT product_id, user_id FROM orders WHERE ...;-- 第二步:分别查产品和用户
SELECT * FROM products WHERE id IN (100,101,102);
SELECT name FROM users WHERE id IN (1,2,3);

✅ 方案3:限制返回数据量

-- 只查需要的列(不要搬整个书架)
SELECT id, name FROM users; -- 代替 SELECT *-- 限制结果数量(只拿前10本书)
SELECT * FROM products LIMIT 10;

✅ 方案4:避免全模糊查询

-- 改用右模糊(允许使用索引)
SELECT * FROM users WHERE name LIKE '张%'; -- 全文检索方案(专业解决方案)
ALTER TABLE products ADD FULLTEXT(name);
SELECT * FROM products WHERE MATCH(name) AGAINST('手机');

3.小结

其实MyBatis到这里还尚未结束,但考虑文章篇幅过长,剩下一些内容如动态sql等内容将放到随后的杂谈篇进行,大家敬请期待~

另外最后的最后,欢迎大家加入我的社区哦,初创社区难免经验不足,请大家多多包涵,也欢迎大家前来多多交流。

爱吃烤鸡翅的酸菜鱼社区-CSDN社区云https://bbs.csdn.net/forums/aaa1f71356f6475db42ea9ea09a392bc?spm=1001.2014.3001.6682

http://www.dtcms.com/a/263866.html

相关文章:

  • python高级变量VIII
  • 转录组分析流程(四):Cox+Lasso筛选预后基因
  • JVM内存模型与垃圾回收机制分析
  • 【java链式调用流操作】
  • Python实现NuScenes数据集可视化:从3D边界框到2D图像的投影原理与实践
  • mac部署dify
  • 笔记/计算机网络
  • 【数据结构】 排序算法
  • beego打包发布到Centos系统及国产麒麟系统完整教程
  • 【文件读取】open | with | as
  • 实体类JavaBean
  • 到底什么是“数字化”?数字化的本质是什么?
  • 从输入到路径:AI赋能的地图语义解析与可视化探索之旅(2025技术全景)
  • 边截图边操作?试试 Snipaste 的浮动贴图功能
  • adc模数转换器
  • Gartner《Choosing Event Brokers to Support Event-DrivenArchitecture》心得
  • OSE3.【Linux】练习:编写进度条及pv命令项目中的进度条函数
  • Postman - API 调试与开发工具 - 标准使用流程
  • 搜索与回溯算法(基础算法)
  • 华为交换机堆叠与集群技术深度解析附带脚本
  • Golang的并发编程实践总结
  • 【pathlib 】Python pathlib 库教程
  • 成都芯谷金融中心文化科技园:打造区域科技活力
  • nginx配置websocket
  • 用java,把12.25.pdf从最后一个点分割,得到pdf
  • Elastic 构建 Elastic Cloud Serverless 的历程
  • CertiK《Hack3d:2025年第二季度及上半年Web3.0安全报告》(附报告全文链接)
  • 61、【OS】【Nuttx】【构建】向量表
  • Redis-7.4.3-Windows-x64下载安装使用
  • 浅谈Docker Kicks in的应用