mybatis动态sql语句

我们现在来做这样一个操作,根据id来更新一条记录。这个要求对于大家来说肯定不难。还是以爸爸表为例。

FatherMapper:

/**
     * 根据id更新
     * @param father
     */
    void updateById(@Param("father") Father father);
<update id="updateById">
        update father set username = #{father.username},
                          age = #{father.age}
        where id = #{father.id}
    </update>

测试类:

@Test
    public void testDynamic(){
        Father father = new Father();
        father.setId(1l);
        father.setUsername("张飞飞");
        this.fatherMapper.updateById(father);
    }

大家可以看到,由于我的疏忽大意,我忘了设置年龄了。我们看看数据库表中id=1的是谁。

好饿,我们执行一下看看结果。

很明显,通过sql语句,由于我没有传递age字段值,所以将age变为了null,我们来看看数据库

这个案例毕竟是我写的,我知道哪个字段没有传递,但是实际开发中,我们一般都是前端传递过来的参数或者查询出来的,根本不知道哪个字段是不是空或者是别的情况。这时候就可以用mybatis提供的动态sql语句来进行控制。

我们在mapper中新建一个方法,

 /**
     * 根据id更新,有值的更新,为null或者""的不更新
     * @param father
     */
    void updateSelectiveById(@Param("father")Father father);

对应的动态sql

<update id="updateSelectiveById" >
    update father
    <set>
        <!--
        set 标签表示动态更新,if 标签就是更新当前字段的条件,大家一眼就看出这不就是java的语法。
        是的,就是java的语法。test中的意思表示:username字段不为null并且username去除空格后
        的长度必须大于0,满足这个条件才对username进行更新。而age字段是Integer类型。所以只需
        判断是不是等于null,但是仍然可以进行各种判断
        -->
        <if test="father.username != null and father.username.trim().length > 0">
            username = #{father.username},
        </if>
        <if test="father.age !=null">
            age = #{father.age},
        </if>
    </set>
    where id = #{father.id}
</update>

就是这么简单。test中的条件千变万化,大家可以灵活运用,也可以用or连接条件,具体取决于你的实际情况。上面提到由于age是Integer类型。所以只需判断不是null即可,但是年龄不可能是负数吧。所以可以再加个条件,年龄>0才更新,我们还是可以借助java的函数进行条件约束。

<update id="updateSelectiveById" >
        update father
        <set>
            <!--
            set 标签表示动态更新,if 标签就是更新当前字段的条件,大家一眼就看出这不就是java的语法。
            是的,就是java的语法。test中的意思表示:username字段不为null并且username去除空格后
            的长度必须大于0,满足这个条件才对username进行更新。而age字段是Integer类型。所以只需
            判断是不是等于null,但是仍然可以进行各种判断
            -->
            <if test="father.username != null and father.username.trim().length > 0">
                username = #{father.username},
            </if>
            <!--调用java的比较大小方法-->
            <if test="father.age !=null and father.age.compareTo(0)>0">
                age = #{father.age},
            </if>
        </set>
        where id = #{father.id}
    </update>

我我们看测试类打印的sql

果然,没有对我们的age进行更新。总之这里大家发挥自己的想象。

如果比较的是八大基本类型和对应包装类+string,对这些进行等值(==)比较,个人建议调用toString方法再进行equals。

比如我现在规定,年龄是50才能进行更新年龄。那么我们可以这么写

<if test="father.age !=null and father.age.toString().equals('50')">
                age = #{father.age},
            </if>

这样就进行了等值约束校验。年龄必须是50才能进行更新年龄。

好的,这就是动态进行更新操作,接下来还有动态insert、动态查询。稍作休息。

在进行字符串的等值比较的时候,如果传递的字符串是数字类型,比如username='123',那么这时候比较的话应该这样写

<if test="father.username != null and father.username.equals('2'.toString())">
                username = '张小飞',
            </if>

动态insert很简单,死记硬背下来

    <insert id="insertSelective">
        insert into father
        <trim prefix="(" suffix=")" suffixOverrides=",">
            <if test="father.username !=null and father.username.trim().length()>0">
                username,
            </if>
            <if test="father.age != null">
                age,
            </if>
        </trim>
        <trim prefix="values (" suffix=")" suffixOverrides=",">
            <if test="father.username !=null and father.username.trim().length()>0">
                #{father.username},
            </if>
            <if test="father.age != null">
                #{father.age},
            </if>
        </trim>
    </insert>

那么还有个动态查询,这个要重点掌握下。

现在有个需求,查询姓名中带“小”字的,年龄大于30的

/**
     * 根据username和年龄查询
     * username用来模糊查询,age用来范围查询
     * @param father
     * @return
     */
    List<Father> selectByUsernameAndAge(@Param("father") Father father);

关键是xml文件中的sql怎么写

<select id="selectByUsernameAndAge" resultType="com.bky.entity.Father">
        select * from father
        <!--
        where标签就是替代了 where关键字
        username模糊查询,由于不好进行百分号连接
        我们用sql提供的函数concat来实现模糊查询
        关于age里面的范围查询条件,各种大于小于的符号,请看下面表格
        这里我写的是大于号
        -->
        <where>
            <if test="father.username !=null and father.username.trim().length>0">
               and username like concat('%',#{father.username},'%')
            </if>
            <if test="father.age !=null and father.age.compareTo(30)>0">
               and age &gt; #{father.age}
            </if>
        </where>
    </select>

关于mybatis中xml文件的比较运算符的表达方式

中文名称 数学符号 mybatis第一种写法 mybatis第二种写法
大于号 > &gt;

<![CDATA[>]]>

大于等于号 >= &gt;= <![CDATA[>=]]>
小于 < &lt; <![CDATA[<]]>
小于等于 <= &lt;= <![CDATA[<=]]>
       
       
<select id="selectByUsernameAndAge" resultType="com.bky.entity.Father">
        select * from father
        <where>
            <if test="father.username !=null and father.username.trim().length>0">
               and username like concat('%',#{father.username},'%')
            </if>
            <if test="father.age !=null and father.age.compareTo(30)>0">
               and age <![CDATA[>]]> #{father.age}
            </if>
        </where>
    </select>

 

posted @   诸葛匹夫  阅读(26)  评论(0编辑  收藏  举报
编辑推荐:
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
点击右上角即可分享
微信分享提示