一.动态SQL
动态 SQL 是Mybatis的强大特性之⼀,能够完成不同条件下不同的 sql 拼接
下面我只介绍比较常用的动态SQL标签 ,想要了解更多标签可以参考官方文档:https://mybatis.net.cn/dynamic-sql.html
1.1 <if> 标签
if 标签 是 MyBatis 动态 SQL 最常用的标签,作用是根据条件动态拼接 SQL 片段,解决「不同条件下执行不同 SQL」的问题,比如多条件查询、非空字段更新 / 插入等场景。
语法:
XML
<if test="条件表达式">
需要拼接的 SQL 片段
</if>
接口定义:
java
Integer insertUserByCondition(UserInfo userInfo);
Mapper.xml 实现:
XML
<insert id="insertUserByCondition">
INSERT INTO userinfo (
username,
`password`,
age,
<if test="gender != null">
gender,
</if>
phone)
VALUES (
#{username},
#{age},
<if test="gender != null">
#{gender},
</if>
#{phone})
</insert>
使用注解实现(不推荐):
把上面SQL(包括标签),使用<script></script>标签括起来就可以
java
@Insert("<script>" +
"INSERT INTO userinfo (username,`password`,age," +
"<if test='gender!=null'>gender,</if>" +
"phone)" +
"VALUES(#{username},#{age}," +
"<if test='gender!=null'>#{gender},</if>" +
"#{phone})"+
"</script>")
Integer insertUserByCondition(UserInfo userInfo);
1.2 <trim>标签
<trim> 是 MyBatis 中用于修剪 SQL 片段首尾多余字符的标签,常配合<if> 使用,解决「动态拼接 SQL 时首尾多出 AND/OR/ 逗号」的问题
语法:
XML
<trim prefix="前缀" suffix="后缀" prefixOverrides="要移除的前缀字符" suffixOverrides="要移除的后缀字符">
动态拼接的 SQL 片段
</trim>
| 属性 | 作用 | 示例值 |
|---|---|---|
prefix |
给拼接后的 SQL 片段添加前缀 (比如 ( 或 WHERE) |
prefix="WHERE" |
suffix |
给拼接后的 SQL 片段添加后缀 (比如 ) 或 VALUES) |
suffix=")" |
prefixOverrides |
移除 拼接后 SQL 片段开头 的指定字符(比如 AND/OR) |
prefixOverrides="AND" |
suffixOverrides |
移除 拼接后 SQL 片段结尾 的指定字符(比如 ,) |
suffixOverrides="," |
注意:它会根据内部动态拼接的 SQL 片段,自动决定是否添加前缀 / 后缀,以及是否移除首尾多余的字符,完全不需要我们手动判断
调整 Mapper.xml 的插入语句为:
XML
<insert id="insertUserByCondition">
INSERT INTO userinfo
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="username !=null">
username,
</if>
<if test="password !=null">
`password`,
</if>
<if test="age != null">
age,
</if>
<if test="gender != null">
gender,
</if>
<if test="phone != null">
phone,
</if>
</trim>
VALUES
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="username !=null">
#{username},
</if>
<if test="password !=null">
#{password},
</if>
<if test="age != null">
#{age},
</if>
<if test="gender != null">
#{gender},
</if>
<if test="phone != null">
#{phone}
</if>
</trim>
</insert>
1.3 <where>标签
<where> 是 MyBatis 为WHERE 子句量身定制 的标签,本质是 <trim> 的「简化版」,专门解决「动态查询时 WHERE 子句的拼接问题」,比手动写<trim> 更简洁、语义更清晰。
核心语法:
XML
<where>
<if test="条件1">AND/OR 条件1的SQL片段</if>
<if test="条件2">AND/OR 条件2的SQL片段</if>
<!-- 更多if条件 -->
</where>
核心作用:
- 自动为条件块添加
WHERE关键字(仅当内部有有效条件时); - 自动剔除条件块开头多余的
AND或OR关键字。
注意:<where> 标签是 <trim perfix="where perfixOverrides = "AND" | "OR" > 的简化写法,规则完全一致。
接口定义:
java
List<UserInfo> queryByCondition();
Mapper.xml 实现:
XML
<select id="queryByCondition" resultType="com.example.demo.model.UserInfo">
select id, username, age, gender, phone, delete_flag, create_time,
update_time
from userinfo
<where>
<if test="age != null">
and age = #{age}
</if>
<if test="gender != null">
and gender = #{gender}
</if>
<if test="deleteFlag != null">
and delete_flag = #{deleteFlag}
</if>
</where>
</select>
1.4 <set> 标签
<set>是 MyBatis 提供的动态 SQL 核心标签 ,专用于 UPDATE 语句的 SET子句动态拼接,是<trim>标签针对更新场景的语法糖(简化封装),其核心定义可拆解为:
核心语法:
XML
<update id="方法名" parameterType="参数类型(如实体类全限定名)">
UPDATE 表名
<set>
<!-- 动态更新字段:每个字段后可加逗号,<set> 自动处理 -->
<if test="字段名 != null [and 字段名 != '']">
数据库字段名 = #{参数名},
</if>
<!-- 可添加多个 <if> 标签,对应多个更新字段 -->
</set>
WHERE 主键字段 = #{主键参数} <!-- 必须加,防止全表更新 -->
</update>
功能定位 :解决手动拼接 UPDATE 语句的 SET 子句时,因字段条件动态变化导致的「末尾多余逗号」「无有效字段时生成空 SET 子句」等 SQL 语法错误问题;
核心规则:
- 仅当内部包含有效更新字段(非空的
<if>条件块)时,才会在拼接结果前添加SET关键字; - 自动剔除拼接结果末尾多余的英文逗号(
,); - 无有效更新字段时,不生成任何
SET相关内容(避免UPDATE table WHERE ...这类语法错误)。
注意:<set> 标签也可以使用 <trim prefix="set" suffixOverrides=","> 代替,这两个的功能完全一致
接口定义:
java
Integer updateUserByCondition(UserInfo userInfo);
Mapper.xml 实现:
XML
<update id="updateUserByCondition">
update userinfo
<set>
<if test="username != null">
username = #{username},
</if>
<if test="age != null">
age = #{age},
</if>
<if test="deleteFlag != null">
delete_flag = #{deleteFlag},
</if>
</set>
where id = #{id}
</update>
1.5 <foreach>标签
<foreach>标签是 MyBatis 框架中最常用的动态 SQL 标签之一,核心作用是遍历集合(List/Set/ 数组 / Map),并根据集合元素动态拼接 SQL 语句(比如批量插入、IN 条件查询等)。
<foreach>标签的核心属性如下(前 4 个是最常用的):
| 属性名 | 作用 |
|---|---|
collection |
绑定方法参数中的集合,如List,Set,Map或数组对象 |
item |
遍历时的每一个对象,给每一个对象取的别名 |
separator |
元素之间的分隔符 |
open |
语句块开头的字符串 |
close |
语句块结尾得字符串 |
接口定义:
java
void deleteByIds(List<Integer> ids);
Mapper.xml 实现:
XML
<delete id="deleteByIds">
delete from userinfo
where id in
<foreach collection="ids" item="id" separator="," open="(" close=")">
#{id}
</foreach>
</delete>
1.6 <include> 标签
<include> 标签是 MyBatis 中用于复用 SQL 片段的核心标签,能有效解决 SQL 代码冗余问题(比如多个 SQL 语句共用相同的字段列表、WHERE 条件等),提升代码的可维护性。
简单来说,<include>就像编程里的 "复制粘贴",但更优雅 ------ 你可以把重复的 SQL 片段定义在<sql> 标签里,然后在需要的地方用<include>引用它。
核心语法:
- 定义可复用的sql片段(使用 <sql> 标签)
XML
<sql id="allColumn">
id, username, age, gender, phone, delete_flag, create_time, update_time
</sql>
- 引用sql片段 (使用<include> 标签)
XML
<select id="queryAllUser" resultMap="BaseMap">
select
<include refid="allColumn"></include>
from userinfo
</select>
<select id="queryById" resultType="com.example.demo.model.UserInfo">
select
<include refid="allColumn"></include>
from userinfo where id= #{id}
</select>
总结使用流程:先通过<sql id="xxx">定义片段,再通过<include refid ="xxx">引用;
二. MyBatis Generator
MyBatis Generator是⼀个为MyBatis框架设计的代码成成⼯具, 它可以根据数据库表结构自动生成相应 的Java 实体类 , Mapper接口 以及SQL映射文件,简化数据访问层的编码工作,使得开发者可以更专注于 业务逻辑的实现. 接下来我们看下,如何使用 MyBatisGenerator来生成代码.
2.1 引入插件
XML
<plugin> <groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.3.6</version>
<executions>
<execution>
<id>Generate MyBatis Artifacts</id>
<phase>deploy</phase>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
<configuration>
<!--generator配置⽂件所在位置 -->
<configurationFile>src/main/resources/mybatisGenerator/generatorConfig.xml</con
figurationFile>
<!-- 允许覆盖⽣成的⽂件, mapxml不会覆盖, 采⽤追加的⽅式-->
<overwrite>true</overwrite>
<verbose>true</verbose>
<!--将当前pom的依赖项添加到⽣成器的类路径中-->
<includeCompileDependencies>true</includeCompileDependencies>
</configuration>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.33</version>
</dependency>
</dependencies>
</plugin>
上面的有些内容属于模板,实际需要按情况进行修改,比如<configurationFile>中的路径要和你创建的文件的路径保持一致
2.2 添加generatorConfig.xml并修改
⽂件路径和上述配置保持⼀致:

完善文件内容
XML
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<!-- 配置⽣成器 -->
<generatorConfiguration>
<!-- ⼀个数据库⼀个context -->
<context id="MysqlTables" targetRuntime="MyBatis3Simple">
<!--禁⽤⾃动⽣成的注释-->
<commentGenerator>
<property name="suppressDate" value="true"/>
<property name="suppressAllComments" value="true" />
</commentGenerator>
<!--数据库连接信息-->
<jdbcConnection driverClass="com.mysql.jdbc.Driver"
connectionURL="jdbc:mysql://127.0.0.1:3306/java_blog_spring?
serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true"
userId="root"
password="root">
</jdbcConnection>
<!-- ⽣成实体类, 配置路径 -->
<javaModelGenerator targetPackage="com.example.demo.model"
targetProject="src/main/java" >
<property name="enableSubPackages" value="false"/>
<property name="trimStrings" value="true"/>
</javaModelGenerator>
<!-- ⽣成mapxml⽂件 -->
<sqlMapGenerator targetPackage="mapper"
targetProject="src/main/resources" >
<property name="enableSubPackages" value="false" />
</sqlMapGenerator>
<!-- ⽣成mapxml对应client,也就是接⼝mapper -->
<javaClientGenerator targetPackage="com.example.demo.mapper"
targetProject="src/main/java" type="XMLMAPPER" >
<property name="enableSubPackages" value="false" />
</javaClientGenerator>
<!-- table可以有多个,tableName表⽰要匹配的数据库表 -->
<table tableName="user" domainObjectName="UserInfo"
enableSelectByExample="true"
enableDeleteByExample="true" enableDeleteByPrimaryKey="true"
enableCountByExample="true"
enableUpdateByExample="true">
2.3 生成文件

双击运行即可根据 generatorConfig.xml 中的具体配置 生成一个表 的Java实体类,mapper接口,mapper接口对应的XML文件