• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录

奋斗的软件工程师

  • 博客园
  • 联系
  • 订阅
  • 管理

公告

View Post

MyBatis 动态 SQL 详解与实践

MyBatis 动态 SQL 详解与实践

引言

在开发中,我们经常需要根据不同的条件动态生成 SQL 语句。如果使用传统的 JDBC 或其他框架,拼接 SQL 语句会非常繁琐且容易出错。MyBatis 提供了强大的动态 SQL 功能,能够帮助我们轻松应对复杂的查询需求。本文将详细介绍 MyBatis 动态 SQL 的常用标签及其使用场景,并结合实际案例进行演示。


什么是动态 SQL?

动态 SQL 是 MyBatis 的核心特性之一,它允许我们根据不同的条件动态生成 SQL 语句。通过使用 MyBatis 提供的动态 SQL 标签,我们可以避免手动拼接 SQL 的繁琐操作,同时减少出错的可能性。

动态 SQL 的优势

  1. 灵活性:根据条件动态生成 SQL 语句。
  2. 简洁性:减少手动拼接 SQL 的代码量。
  3. 可维护性:动态 SQL 更易于阅读和维护。

动态 SQL 常用标签

MyBatis 提供了多种动态 SQL 标签,以下是常用的几种:

标签名称 作用描述
<if> 条件判断,用于根据条件动态拼接 SQL 片段。
<choose> 多条件分支判断,类似于 Java 中的 switch 语句。
<when> 与 <choose> 配合使用,表示一个分支条件。
<otherwise> 与 <choose> 配合使用,表示默认分支。
<trim> 用于去除 SQL 语句中多余的关键字(如 AND、OR)或符号(如逗号)。
<where> 动态生成 WHERE 子句,并去除多余的 AND 或 OR。
<set> 动态生成 SET 子句,并去除多余的逗号。
<foreach> 遍历集合或数组,常用于 IN 查询或批量操作。

动态 SQL 实践案例

1. <if> 标签:条件判断

需求:查询男性用户,如果输入了用户名,则按用户名模糊查询;如果没有输入用户名,则查询所有男性用户。

接口方法

List<User> queryLikeUserName(@Param("userName") String userName);

SQL 映射

<select id="queryLikeUserName" resultType="User">
    SELECT * FROM tb_user WHERE sex = '男'
    <if test="userName != null and userName.trim() != ''">
        AND user_name LIKE '%${userName}%'
    </if>
</select>

测试

@Test
public void testQueryLikeUserName() {
    List<User> users = userMapper.queryLikeUserName("张");
    users.forEach(System.out::println);
}

说明:

  • <if> 标签用于判断 userName 是否为空,如果不为空,则拼接模糊查询条件。
  • 注意:${} 用于直接拼接字符串,#{} 用于预编译参数。

2. <choose>、<when>、<otherwise> 标签:多条件分支

需求:根据用户名或住址查询男性用户。如果输入了用户名,则按用户名模糊查询;如果输入了住址,则按住址查询;如果两者都未输入,则查询用户名为“孙悟空”的用户。

接口方法

List<User> queryByUserNameOrAddress(
    @Param("userName") String userName, 
    @Param("address") String address
);

SQL 映射

<select id="queryByUserNameOrAddress" resultType="User">
    SELECT * FROM tb_user WHERE sex = '男'
    <choose>
        <when test="userName != null and userName.trim() != ''">
            AND user_name LIKE '%${userName}%'
        </when>
        <when test="address != null and address.trim() != ''">
            AND address = #{address}
        </when>
        <otherwise>
            AND user_name = '孙悟空'
        </otherwise>
    </choose>
</select>

测试

@Test
public void testQueryByUserNameOrAddress() {
    List<User> users = userMapper.queryByUserNameOrAddress(null, "花果山");
    users.forEach(System.out::println);
}

说明:

  • <choose> 类似于 Java 中的 switch 语句,<when> 表示分支条件,<otherwise> 表示默认分支。

3. <where> 标签:动态生成 WHERE 子句

需求:根据用户名和住址查询用户。如果输入了用户名,则按用户名查询;如果输入了住址,则按住址查询;如果两者都输入,则同时满足两个条件。

接口方法

List<User> queryByUserNameAndAddress(
    @Param("userName") String userName, 
    @Param("address") String address
);

SQL 映射

<select id="queryByUserNameAndAddress" resultType="User">
    SELECT * FROM tb_user
    <where>
        <if test="userName != null and userName.trim() != ''">
            AND user_name = #{userName}
        </if>
        <if test="address != null and address.trim() != ''">
            AND address = #{address}
        </if>
    </where>
</select>

测试

@Test
public void testQueryByUserNameAndAddress() {
    List<User> users = userMapper.queryByUserNameAndAddress("孙悟空", null);
    users.forEach(System.out::println);
}

说明:

  • <where> 标签会自动生成 WHERE 关键字,并去除多余的 AND 或 OR。

4. <set> 标签:动态生成 SET 子句

需求:根据用户 ID 更新用户信息。如果某个字段为 null,则不更新该字段。

接口方法

void updateSelectiveUser(User user);

SQL 映射

<update id="updateSelectiveUser">
    UPDATE tb_user
    <set>
        <if test="userName != null and userName.trim() != ''">
            user_name = #{userName},
        </if>
        <if test="address != null and address.trim() != ''">
            address = #{address},
        </if>
    </set>
    WHERE id = #{id}
</update>

测试

@Test
public void testUpdateSelectiveUser() {
    User user = new User();
    user.setId(1);
    user.setUserName("悟空");
    userMapper.updateSelectiveUser(user);
}

说明:

  • <set> 标签会自动生成 SET 关键字,并去除多余的逗号。

5. <foreach> 标签:遍历集合

需求:根据多个用户 ID 查询用户信息。

接口方法

List<User> queryByIds(@Param("ids") List<Integer> ids);

SQL 映射

<select id="queryByIds" resultType="User">
    SELECT * FROM tb_user WHERE id IN
    <foreach collection="ids" item="id" separator="," open="(" close=")">
        #{id}
    </foreach>
</select>

测试

@Test
public void testQueryByIds() {
    List<Integer> ids = Arrays.asList(1, 2, 3);
    List<User> users = userMapper.queryByIds(ids);
    users.forEach(System.out::println);
}

说明:

  • <foreach> 标签用于遍历集合或数组,常用于 IN 查询或批量操作。

总结

MyBatis 的动态 SQL 功能极大地简化了复杂查询的实现过程。通过灵活使用 <if>、<choose>、<where>、<set> 和 <foreach> 等标签,我们可以轻松应对各种动态查询需求。希望本文的内容能够帮助你更好地掌握 MyBatis 动态 SQL 的使用技巧,提升开发效率!


版权声明:本文为原创文章,转载请注明出处。

互动话题
你在使用 MyBatis 动态 SQL 时遇到过哪些问题?欢迎在评论区分享你的经验和心得!如果你有其他技术问题,也欢迎留言讨论! 😊

posted on 2025-01-05 11:11  周政然  阅读(218)  评论(0)    收藏  举报

刷新页面返回顶部
 
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3