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 > #{father.age}
</if>
</where>
</select>
关于mybatis中xml文件的比较运算符的表达方式
中文名称 | 数学符号 | mybatis第一种写法 | mybatis第二种写法 |
大于号 | > | > |
<![CDATA[>]]> |
大于等于号 | >= | >= | <![CDATA[>=]]> |
小于 | < | < | <![CDATA[<]]> |
小于等于 | <= | <= | <![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>
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 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语句:使用策略模式优化代码结构