MyBatis学习day4-动态sql标签


学会了使用Mapper接口查询数据之后,我们再来学习一下Mybatis的动态sql标签,它是用来更灵活更精确的拼接sql语句用的

1.if标签

了解if标签之前我们先在UserMapper接口中创建一个方法SelectTest(User u),它的功能是跟根据参数查询相同用户性别、模糊查询用户姓名,查询用户国家id(cid)并返回查询列表;对应到Mapper.xml文件中就是这样

<select id="SelectTest" parameterType="User" resultType="User">
    SELECT *
    FROM USER
    WHERE
    u_sex=#{u_sex}
    AND u_username like "%"#{u_username}"%"
    AND u_cid=#{u_cid}
</select>

然后我们测试一下

UserMapper um=session.getMapper(UserMapper.class);
User user=new User();
user.setU_username("王");
user.setU_sex("1");
user.setU_cid(1);
List<User> rs=um.SelectTest(user);
for(User u:rs){
    System.out.println(u);
}

输出结果

User{u_id=1, u_username='老王', u_password='123', u_sex='1', u_createTime=null, u_cid=1}
User{u_id=4, u_username='王司机', u_password='666', u_sex='1', u_createTime=null, u_cid=1}
User{u_id=9, u_username='王五', u_password='abc', u_sex='1', u_createTime=null, u_cid=1}

跟预期结果一样;接下来我们考虑一个问题,如果上述我们常见的user对象的国籍id没有设置,也就是说值为null,而在mysql中null值也会相互匹配,但是我们现在希望的效果是如果国籍id忘记设置了,我们要把u_cid匹配的那一行条件去掉,该怎么做呢?

显然我们手动删除太硬核了,万一下次又要用到怎么办。所以我们就要用到if标签进行判断,把sql语句改成如下形式

<select id="SelectTest" parameterType="User" resultType="User">
    SELECT *
    FROM USER
    WHERE
    <if test="u_sex!=null">
        u_sex=#{u_sex}
    </if>
    <if test="u_username!=null">
        AND u_username like "%"#{u_username}"%"
    </if>
    <if test="u_cid!=null">
        AND u_cid=#{u_cid}
    </if>
</select>

if标签内含一个test属性,也就是判断的条件,如果条件的值为真,就把标签内的语句拼接上去,这样就防止了上述问题

在这里插入图片描述

但是…还是有问题.我们试试让u_sex为null会怎么样

在这里插入图片描述

出现了错误…原因是最后拼接的sql语句变成了“SELECT * FROM USER WHERE AND u_username like “%”?"%" AND u_cid=?”

显然,where后面直接跟and是不符合语法的,那该怎么办呢?我们可以用接下来的where标签解决这个问题

2.where-trim标签

对于上述问题,我们有一个很简单的解决方法–将sql语句中的where删除、用where标签把之后的内容包裹住,where标签就是用来剔除AND/OR 冲突的,具体代码如下

<select id="SelectTest" parameterType="User" resultType="User">
    SELECT *
    FROM USER
    <where>
        <if test="u_sex!=null">
            u_sex=#{u_sex}
        </if>
        <if test="u_username!=null">
            AND u_username like "%"#{u_username}"%"
        </if>
        <if test="u_cid!=null">
            AND u_cid=#{u_cid}
        </if>
    </where>
</select>

在这里插入图片描述

这样就解决了,是不是so easy?然而我们还有问题–如果我们是把AND放在条件后面会怎么样,像这样

<select id="SelectTest" parameterType="User" resultType="User">
    SELECT *
    FROM USER
    <where>
        <if test="u_sex!=null">
            u_sex=#{u_sex} AND
        </if>
        <if test="u_username!=null">
            u_username like "%"#{u_username}"%" AND
        </if>
        <if test="u_cid!=null">
            u_cid=#{u_cid}
        </if>
    </where>
</select>

然后我们让u_cid为null,测试一下

在这里插入图片描述

还是出错了…后面多出了一个AND,看来where标签只能去掉前缀AND= =

不慌,我们还有办法

我们可以用trim标签替换where标签,这里先介绍一下trim标签的各种属性

在这里插入图片描述

prefix是给标签中的内容添加一个前缀,比如我们设置prefix=“where” 就相当于是在下面的语句之前拼接一个where,

prefixOverrides是用来剔除前缀的,比如我们设置prefixOverrides=“AND",就可以剔除每个条件前多余的AND前缀,就像上面的where标签

同理,

suffix是给标签中的内容添加一个后缀,

suffixOverrides是用来剔除前缀的,比如我们设置suffixOverrides=“AND",就可以剔除每个条件后多余的AND后缀

知道了这些属性之后我们就自然知道怎么解决上面的问题了,改成如下即可

<select id="SelectTest" parameterType="User" resultType="User">
    SELECT *
    FROM USER
    <trim prefix="where" suffixOverrides="AND">
        <if test="u_sex!=null">
            u_sex=#{u_sex} AND
        </if>
        <if test="u_username!=null">
            u_username like "%"#{u_username}"%" AND
        </if>
        <if test="u_cid!=null">
            u_cid=#{u_cid} 
        </if>
    </trim>
</select>

在这里插入图片描述
在这里插入图片描述

3.set标签

现在我们又有一个需求,我们要修改某一个id的用户名、密码、性别。

我们先在Mapper接口中定义方法UpdateTest(User u),然后在Mapper.xml文件里写sql语句,当然非空条件判断也要加一下

<update id="UpdateTest" parameterType="User">
    update user
    set
    <if test="u_username!=null">
        u_username=#{u_username},
    </if>
    <if test="u_password!=null">
        u_password=#{u_password},
    </if>
    <if test="u_sex!=null">
        u_sex=${u_sex}
    </if>
    where
    u_id=#{u_id}
</update>

然后进行测试,先不提交事务,就看看有没有出错

在这里插入图片描述

O的K,然后还是和之前类似的问题,如果去掉了最后一个条件就会多出一个逗号,导致sql语法错误.

那么该怎么办呢,我们需要用到set标签,把需要set的语句都包裹住,这样就可以去掉后缀逗号了。

<update id="UpdateTest" parameterType="User">
    update user
    <set>
        <if test="u_username!=null">
            u_username=#{u_username},
        </if>
        <if test="u_password!=null">
            u_password=#{u_password},
        </if>
        <if test="u_sex!=null">
            u_sex=${u_sex}
        </if>
    </set>
    where
    u_id=#{u_id}
</update>

在这里插入图片描述

当然也还是可以用trim标签

4.foreach标签

在sql语句中,我们可以用IN指定查询多条数据,如指定u_id IN (1,3,5)就可以指定查询u_id分别为1,3,5的记录,那么我们怎么通过用户输入确定IN后面遍历的内容呢,这就是我们接下来要讲的foreach标签

我们一样先在Mapper接口中定义一个新方法SelectListTest(Integer[] list),然后在Mapper.xml文件中实现,代码如下

<select id="SelectListTest" resultType="User">
    select *
    from user
    where u_id
    in
    <foreach collection="array" item="id" open="(" close=")" separator=",">
        #{id}
    </foreach>
</select>

解释一下,foreach标签中的collection属性用于指定传入的参数类型,如果是数组就是array,如果是容器类就是collection或者list,item就是用于遍历的临时元素,相当于我们通常写的for(int i:array)中的i一样,用于承载数组中每个元素的内容。open跟close就是用来补全原sql语句中的括号,separator用来充当分隔符

最后我们来测试一下

在这里插入图片描述

ok,测试与预期一样

5.sql标签

Mybatis另外还有一个sql标签,它是用于提取每个sql语句中重复的部分,下次可以统一运用,比如之前我们很多的sql语句都包含“select * from user”这条语句,我们就可以把它提取出来,取一个id,然后其他地方要用的话就用include标签导入拼接,具体用法如下

<sql id="selectAll">
    select * from user
</sql>

<select id="selectUserById" parameterType="Integer" resultType="User">
    <include refid="selectAll"/>
    where u_id=#{id}
</select>
<select id="selectUserByName" parameterType="String" resultType="User">
    <include refid="selectAll"/>
    where u_username like "%"#{username}"%"
</select>
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值