MyBatis 动态 SQL 详解与实践
MyBatis 动态 SQL 详解与实践
引言
在开发中,我们经常需要根据不同的条件动态生成 SQL 语句。如果使用传统的 JDBC 或其他框架,拼接 SQL 语句会非常繁琐且容易出错。MyBatis 提供了强大的动态 SQL 功能,能够帮助我们轻松应对复杂的查询需求。本文将详细介绍 MyBatis 动态 SQL 的常用标签及其使用场景,并结合实际案例进行演示。
什么是动态 SQL?
动态 SQL 是 MyBatis 的核心特性之一,它允许我们根据不同的条件动态生成 SQL 语句。通过使用 MyBatis 提供的动态 SQL 标签,我们可以避免手动拼接 SQL 的繁琐操作,同时减少出错的可能性。
动态 SQL 的优势
- 灵活性:根据条件动态生成 SQL 语句。
- 简洁性:减少手动拼接 SQL 的代码量。
- 可维护性:动态 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 时遇到过哪些问题?欢迎在评论区分享你的经验和心得!如果你有其他技术问题,也欢迎留言讨论! 😊