Mybatis从入门到精通系列 08 —— 动态 SQL 语句

  Mybatis 的映射文件中,前面我们的 SQL 都是比较简单的,有些时候业务逻辑复杂时,我们的 SQL 是动态变化的,此时在前面的学习中我们的 SQL 就不能满足要求了。那么本文针对 Mybatis 动态 SQL 语句进行简单的操作。

后文应用 typeAliases 标签指定了所有实体类都注册别名,并且类名就是别名,参考链接如下:
Mybatis从入门到精通系列 06——properties 和 typeAliase 标签总结
在这里插入图片描述



一、动态 SQL 的 if 标签

  我们根据实体类的不同取值,使用不同的 SQL 语句来进行查询。比如在 id 如果不为空时可以根据 id 查询,如果 username 不同空时还要加入用户名作为条件。这种情况在我们的多条件组合查询中经常会碰到。

持久层 Dao 接口:

/**
 * 使用 if 标签
 */
List<User> findUserIfLabelByCondition(User user);

持久层 Dao 映射配置:

<!--根据条件查询,if 标签的使用-->
<select id="findUserIfLabelByCondition" resultType="user" parameterType="user">
    select * from user where 1 = 1
    <if test="id != null">
        and id = #{id}
    </if>
    <if test="username!= null">
        and username = #{sex}
    </if>
</select>

注意:if 标签的 test 属性中写的是对象的属性名,如果是包装类的对象要使用 OGNL 表达式的写法。
另外要注意 where 1=1 的作用!

测试方法:

/**
 * 测试条件查询
 */
@Test
public void testFindByCondition(){
    User u = new User();
    u.setUsername("老王");
    u.setId(43);
    List<User> users = userDao.findUserIfLabelByCondition(u);
    for (User user:users){
        System.out.println(user);
    }
}

二、动态 SQL 的 where 标签

为了简化上面 where 1=1 的条件拼装,我们可以采用标签来简化开发。

持久层 Dao 接口:

/**
 * 使用 where 标签
 */
List<User> findUserWhereLabelByCondition(User user);

持久层 Dao 映射配置:

<!--根据条件查询,where 标签的使用-->
<select id="findUserWhereLabelByCondition" resultType="user" parameterType="user">
    select * from user
    <where>
        <if test="id != null">
	        and id = #{id}
	    </if>
	    <if test="username!= null">
	        and username = #{sex}
	    </if>
    </where>
</select>

测试方法:

/**
 * 测试条件查询
 */
@Test
public void testFindUserWhereLabelByCondition(){
    User u = new User();
    u.setUsername("老王");
    u.setId(43);
    List<User> users = userDao.findUserWhereLabelByCondition(u);
    for (User user:users){
        System.out.println(user);
    }
}

三、动态 SQL 的 foreach 标签

这里我们有一个需求:

当传入多个 id 查询用户信息,用下边下面的 sql 实现:

select * from user where id in ( ? , ? , ? )

这样我们在进行范围查询时,就要将一个集合中的值,作为参数动态添加进来。


3.1 传入 List 集合

持久层 Dao 接口:

/**
 * 根据 list 中提供的id集合,查询用户信息
 */
List<User> findUserInIdsByList(List list);

持久层 Dao 映射配置:

<!--根据 List 实现查询用户列表-->
<select id="findUserInIdsByList" resultType="user" parameterType="list">
    select * from user
    <where>
        <if test="list!=null and list.size()>0">
        <foreach collection="list" open="and id in (" close=")" item="sid" separator=",">
            #{sid}
        </foreach>
        </if>
    </where>
</select>

其中,foreach 标签用于遍历集合,它的属性:

  • collection:代表要遍历的集合元素,注意编写时不要写#{}
  • open:代表语句的开始部分
  • close:代表结束部分
  • item:代表遍历集合的每个元素,生成的变量名
  • separator:代表分隔符

测试方法:

@Test
public void testFindInIdsByList(){
     List<Integer> list = new ArrayList<Integer>();
     list.add(41);
     list.add(42);
     list.add(47);

     List<User> users = userDao.findUserInIdsByList(list);
     for (User user:users){
         System.out.println(user);
     }
 }

3.2 传入包装类 QueryVo

在 QueryVo 中加入一个 List 集合用于封装参数:

(注:这里的 QuryVo 代表的是包装对象,读者可参考以下链接查看关于此类型参数的详情解析)
Mybatis从入门到精通系列 05——Mybatis 传入参数总结

QueryVo 实体类:

public class QueryVo {
    private User user;
    private List<Integer> ids;

    public User getUser(){
        return user;
    }
    
    public void setUser(User user){
        this.user = user;
    }

    public List<Integer> getIds() {
        return ids;
    }

    public void setIds(List<Integer> ids) {
        this.ids = ids;
    }
}

持久层 Dao 接口:

/**
 * 根据 queryvo 中提供的id集合,查询用户信息
 */
 List<User> findUserInIdsByQueryVo(QueryVo vo);

持久层 Dao 映射配置:

<!--根据queryvo中的id集合实现查询用户列表-->
<select id="findUserInIdsByQueryVo" resultType="user" parameterType="queryvo">
    select * from user
    <where>
        <if test="ids != null">
            <foreach collection="ids" open="and id in (" close=")" item="sid" separator=",">
                #{sid}
            </foreach>
        </if>
    </where>
</select>

测试方法:

/**
 * 测试子查询
 */
@Test
public void testFindInIds(){
    QueryVo vo = new QueryVo();
    List<Integer> list = new ArrayList<Integer>();
    list.add(41);
    list.add(42);
    list.add(47);
    vo.setIds(list);
    List<User> users = userDao.findUserInIdsByQueryVo(vo);
    for (User user:users){
        System.out.println(user);
    }
}

四、动态 SQL 的 bind 标签

bind 标签可以使用 OGNL 表达式创建一个变量井将其绑定到上下文中,其主要用于模糊查询,防止 SQL 注入。

持久层 Dao 接口:

/**
 * 使用 bind 标签
 */
List<User> findUserByBindLabel(User user);

持久层 Dao 映射配置:

<select id="findUserByBindLabel" parameterType="user" resultType="user">
 	<!-- bind 中的 username 是 user 的属性名-->        
    <bind name="nameLike" value="'%' + username + '%'"/>
    select * from user where username like #{nameLike}
</select>

测试方法:

 @Test
public void testFindUserByBindLabel(){
    User u = new User();
    u.setUsername("王");

    List<User> users = userDao.findUserByBindLabel(u);
    for (User user:users){
        System.out.println(user);
    }
}

五、动态 SQL 的 set 标签

set 标签是 mybatis 提供的一个智能标记,我一般将其用在修改的 sql 中,例如以下情况:

持久层 Dao 映射配置:

<update id="updateUserBySetLabel" parameterType="user">
	update user
    <set>
        <if test="username != null">username = #{username},</if>
        <if test="sex != null">sex = #{sex},</if>
    </set>
    where id = #{id}
</update>

在上述的代码片段当中,假如说现在三个字段都有值得话,那么上面打印的SQL语句如下:
update user set username=‘xxx’ , sex=‘xx’ where id=‘x’

set标记已经自动帮助我们把最后一个逗号给去掉了。

参考博客:https://www.cnblogs.com/qiankun-site/p/5758383.html


六、动态 SQL 的 trim 标签

  mybatis 的 trim 标签一般用于去除 sql 语句中多余的 and 关键字,逗号,或者给 sql 语句前拼接 “where“、“set“ 以及“values (“ 等前缀,或者添加“)“等后缀,可用于选择性插入、更新、删除或者条件查询等操作。

持久层 Dao 映射配置:

<select id="findUserByTrimLabel" parameterType="user" resultType="user">
 	select * from user
    <trim prefix="WHERE" prefixOverrides="AND">
        <if test="username != null">
            username = #{username}
        </if>
        <if test="sex != null">
            sex = #{sex}
        </if>
    </trim>
</select>

此处对于 trim 标签的使用讲解不是特别清楚,读者可参考以下链接:

参考博客:https://blog.csdn.net/wt_better/article/details/80992014


七、Mybatis 中简化编写的 SQL 片段

Sql 标签中可将重复的 sql 提取出来,使用时用 include 引用即可,最终达到 sql 重用的目的。

定义代码片段:

<!-- 抽取重复的语句代码片段 -->
<sql id="defaultSql">
	select * from user
</sql>

引用代码片段:

<!--配置查询所有-->
<select id="findAll" resultType="user">
    <include refid="defaultUser"></include>/*引用sql标签中的sql语句,refid为sql的id*/
</select>

<!--根据id查询用户-->
<select id="findById" parameterType="INT" resultType="user">
   <include refid="defaultUser"></include> where id = #{id}
</select>

本文针对 Mybatis 中的动态 SQL 语句使用进行了总结归纳,如果大家对文章内容还存在一些疑问,欢迎大家在评论区留言哦~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Xiu Yan

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值