MyBatis进阶:动态SQL与MyBatis Generator插件使用

一.动态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 关键字(仅当内部有有效条件时);
  • 自动剔除条件块开头多余的 ANDOR 关键字。

注意:<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>引用它。

核心语法:

  1. 定义可复用的sql片段(使用 <sql> 标签)
XML 复制代码
<sql id="allColumn">
 id, username, age, gender, phone, delete_flag, create_time, update_time
</sql>
  1. 引用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&amp;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文件

相关推荐
xiangpanf1 小时前
PHP vs Go:30秒读懂核心差异
java·开发语言
爱喝一杯白开水1 小时前
Java List 常用方法全攻略
java·list·排序算法
华农DrLai1 小时前
什么是Prompt模板?为什么标准化的格式能提高稳定性?
数据库·人工智能·gpt·nlp·prompt
李白的粉1 小时前
基于springboot的在线问卷调查系统
java·spring boot·毕业设计·课程设计·源代码·在线问卷调查系统
程序员老乔1 小时前
Java 新纪元 — JDK 25 + Spring Boot 4 全栈实战(一):你的Java该升级了
java·spring boot·python
.select.1 小时前
C++ 单例模式
java·c++·单例模式
鬼蛟1 小时前
Spring MVC
java·spring·mvc
qq_256247051 小时前
Docker 部署 OpenClaw 踩坑实录:Web UI 访问、飞书配对及自定义模型配置
后端
一直都在5722 小时前
JAVA类的加载过程
java·开发语言