MyBatis动态SQL表达式详解
作者:一个双子座的Java攻城狮 发布时间:2023-11-29 00:42:36
动态 sql 简单来讲就是我们能通过条件的设置生成不同的 sql,MyBatis 中常用的动态 sql 表达式主要是有五种:
if
choose (when, otherwise)
trim, where, set
foreach
sql
if
动态 sql 中最常见的场景是根据条件查询,比如要实现一个查询语句,当不传任何参数时查询所有用户,当传了 id 或者 name 时根据条件进行查询,就可以这样写:
<select id="selectUserByMap" parameterType="map" resultType="user">
select * from user where 1=1
<if test="id != null and id!=''">
and id=#{id}
</if>
<if test="name != null and name!=''">
and name=#{name}
</if>
</select>
对应的 mapper 接口如下:
public interface UserMapper {
List<User> selectUserByMap(Map<String,Object> param);
void updateUser(Map<String,Object> param);
}
对应的 Java 代码如下:
Map<String,String> map=new HashMap<String, String>();
map.put("id","1");
map.put("name","javayz");
List<User> users = mapper.selectUserByMap(map);
当 map 中什么都不传时,sql 语句变为:
select * from user where 1=1
当传了 id 或 name 时,分别执行对应的查询。
choose when otherwise
choose 的使用很像 Java 中的 switch 语法,当满足第一个 when 条件时,就不去看后续的条件,如果条件都不满足,则执行 otherwise:
<select id="selectUserByChoose" parameterType="map" resultType="user">
select * from user where 1=1
<choose>
<when test="id != null">
and id=#{id}
</when>
<when test="name != null">
and name=#{name}
</when>
<otherwise>
and 1=1
</otherwise>
</choose>
</select>
trim where set
还记得前面的语法中都写了 where 1=1 吗,至于为什么这样写,目的在于让语法能顺利执行,以 if 语句为例:如果不写 1=1,语法就会变成下面这样:
<select id="selectUserByMap" parameterType="map" resultType="user">
select * from user where
<if test="id != null">
id=#{id}
</if>
<if test="name != null">
and name=#{name}
</if>
</select>
这个时候如果满足了第一个 if 条件,那不会有问题,但是如果只满足第二个条件,语句就会变成:
select * from user where and name=?
语法直接报错。
MyBatis 提供了一种标签来代替 1=1 的写法,where 标签只会在子元素返回任何内容的情况下才插入 “WHERE” 子句。而且,若子句的开头为 “AND” 或 “OR”,where 元素也会将它们去除。
<select id="selectUserByMap" parameterType="map" resultType="user">
select * from user
<where>
<if test="id != null">
and id=#{id}
</if>
<if test="name != null">
and name=#{name}
</if>
</where>
</select>
set 的语法和 where 类似,在更新时会用到 set:
<update id="updateUser" parameterType="map">
update user
<set>
<if test="name != null">name =#{name},</if>
</set>
where id = #{id}
</update>
使用 where 时会用自动去替换掉 and 或者 or,而使用 set 时会动态地在行首插入 SET 关键字,并会删掉额外的逗号。
使用 trim 可以用于去除拼接 sql 时的 and、or 关键字或者逗号等等。
之前使用 where 标签去除了最开始的 and 关键字,用 trim 也同样可以实现:
<select id="selectUserByMap" parameterType="map" resultType="map">
select * from user
<trim prefix="where" prefixOverrides="and">
<if test="id != null">
and id=#{id}
</if>
<if test="name != null">
and name=#{name}
</if>
</trim>
</select>
foreach
foreach 在需要对集合进行遍历的场景中使用很广泛,尤其是在 in 语句中,比如下面这条语句:
select * from user where id in (1,2,3,4)
通过 foreach 实现方式如下,foreach 中的 ids 可以是参数传入的一个 List 集合:
<select id="selectUserByForeach" parameterType="map" resultType="User">
select * from user where id in
<foreach collection="ids" item="id" index="index" open="(" separator="," close=")">
#{id}
</foreach>
</select>
sql片段
通过 sql 片段标签,可以将重复的 sql 提取出来,使用时通过 include 引用即可。
<sql id="select_user_where">
<if test="id != null and id!=''">
and id=#{id}
</if>
<if test="name != null and name!=''">
and name=#{name}
</if>
</sql>
<select id="selectUserByMap" parameterType="map" resultType="user">
select * from user where 1=1
<include refid="select_user_where">
</select>
来源:https://blog.csdn.net/weixin_64061088/article/details/128450087


猜你喜欢
- 前言我们之前讲述的动画都需要主动触发或者是重复执行,那有没有自己触发动画的组件呢?这样我们就可以在 StatelessWidget 里直接使
- @Value获取application.properties配置无效问题无效的原因主要是要注意@Value使用的注意事项:1、不能作用于静态
- 一、背景在Web应用开发中,经常需要使用图表来展示数据,而Echarts是一个非常优秀的图表库。SpringBoot是一个非常流行的Java
- Freemarker 3种循环模式1. map循环举例:<#if vo.urlMap??>
- 目录1.问题引出2.解决办法3.另外一种自定义序列化机制(介绍Externalizable)1.问题引出在某些情况下,我们可能不想对于一个对
- 本文实例讲述了C#验证给定字符串是否为数字的方法。分享给大家供大家参考。具体分析如下:这段C#代码用于验证给定的字符串是否为数字,不能用于验
- 静态数组Java中最基本的数组大家肯定不会陌生:int[] array = new int[6];for (int i = 0; i <
- 1.File对象java封装的一个操作文件及文件夹(目录)的对象。可以操作磁盘上的任何一个文件和文件夹。2.创建文件方式一:根据路径构建一个
- 在Servlet 3.0之前都是使用web.xml文件进行配置,需要增加Servlet、Filter或者Listener都需要在web.xm
- 错误详情:java.lang.NoSuchMethodException: [Lorg.springframework.web.multip
- 本文实例讲述了Android编程之SMS读取短信并保存到SQLite的方法。分享给大家供大家参考,具体如下:Android 之 SMS 短信
- Java微信跳一跳操作指南,指哪挑哪。本文的思路是通过adb来控制手机进行操作,通过java写一个jframe覆盖在手机屏幕上,用鼠标获取跳
- Java注解是在JDK5时引入的新特性,鉴于目前大部分框架(如spring)都使用了注解简化代码并提高编码的效率,因此掌握并深入理解注解对于
- 通常C#使用基于XML的配置文件,不过如果有需要的话,比如要兼顾较老的系统,可能还是要用到INI文件。但C#本身并不具备读写INI文件的AP
- C语言数据结构之二叉树的非递归后序遍历算法前言:前序、中序、后序的非递归遍历中,要数后序最为麻烦,如果只在栈中保留指向结点的指针,那是不够的
- 找到BeanClass并且加载类protected Object createBean(String beanName, RootBeanD
- 默认日志 Logback :默认情况下,Spring Boot会用Logback来记录日志,并用INFO级别输出到控制台。在运行应用程序和其
- 实现目标:使用springMVC前端控制器,跳转到WEB-INF的templates下面的前端页面图示1.目录结构2.创建一个maven的w
- 之前写过一篇刷新加载《RecyclerView上拉加载和下拉刷新(基础版)》 ,这次是进行改装完善。代码中注释的很详细,所以就直接上代码了。
- 1. 可空类型修饰符 ?// 引用类型能用空引用来表示一个不存在的值,但是值类型不能。例如:string str = null;int i