mybatis中的动态SQL

举报
江南一点雨 发表于 2021/08/17 00:02:04 2021/08/17
【摘要】 在实际开发中,数据库的查询很难一蹴而就,我们往往要根据各种不同的场景拼接出不同的SQL语句,这无疑是一项复杂的工作,我们在使用mybatis时,mybatis给我们提供了动态SQL,可以让我们根据具体的业务逻辑来拼接不同的SQL语句。OK,那么我们今天就来看看如何使用mybatis中的动态SQL。 mybatis中的动态SQL主要包含如下几种元素:if、choose、...

在实际开发中,数据库的查询很难一蹴而就,我们往往要根据各种不同的场景拼接出不同的SQL语句,这无疑是一项复杂的工作,我们在使用mybatis时,mybatis给我们提供了动态SQL,可以让我们根据具体的业务逻辑来拼接不同的SQL语句。OK,那么我们今天就来看看如何使用mybatis中的动态SQL。
mybatis中的动态SQL主要包含如下几种元素:if、choose、when、otherwise、trim、where、set以及foreach几种,我们下面分别来看看这几种。

if

if是mybatis动态SQL中的判断元素,这个有点类似于Java中的if语句,不同的是这里的if一般常常和test配合使用。我们来看一个简单的例子:

<select id="getUser" resultMap="u" parameterType="String"> select * from user2 <if test="address!=null and address !=''"> WHERE address LIKE concat('%',#{address},'%') </if> </select>
  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

当用户传入的address不为null或者空字符串的时候,我就加上一个where条件,否则就什么条件都不加入。然后我们再来看看我们在UserMapper这个接口中定义的相关方法:

public List<User> getUser(@Param("address") String address);
  
 
  • 1

我们在调用这个方法的时候,如果传入了address参数,那么查询条件中就有address,否则就没有。来看看测试代码:

SqlSession sqlSession = null; try { sqlSession = DBUtils.openSqlSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); List<User> list = mapper.getUser("西安"); for (User user : list) { System.out.println(user); } sqlSession.commit(); } catch (Exception e) { System.err.println(e.getMessage()); sqlSession.rollback(); } finally { if (sqlSession != null) { sqlSession.close(); } }
  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

查询结果:
这里写图片描述
如果我将查询条件设为空字符串,如下:

SqlSession sqlSession = null; try { sqlSession = DBUtils.openSqlSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); List<User> list = mapper.getUser(""); for (User user : list) { System.out.println(user); } sqlSession.commit(); } catch (Exception e) { System.err.println(e.getMessage()); sqlSession.rollback(); } finally { if (sqlSession != null) { sqlSession.close(); } }
  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

这里写图片描述

小伙伴们注意两个查询结果截图中打印出来的SQL语句的差异。

choose

choose有点类似于Java中的switch,常常配合when和otherwise一起来使用。我们来看一个简单的例子:

<select id="getUser2" resultMap="u"> SELECT * FROM user2 WHERE 1=1 <choose> <when test="id!=null"> AND id=#{id} </when> <when test="address!=null"> AND address=#{address} </when> <when test="username!=null"> AND user_name LIKE concat(#{username},'%') </when> <otherwise> AND 10>id </otherwise> </choose> </select>
  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

在查询条件中,如果用户传来了id,那么我就查询该id的数据,如果用户传来了address,那么我就我们添加address的查询条件,如果用户传来了username,那么我就添加username的查询条件,最后如果用户任何一个查询条件都没有添加进来,那么默认查询条件就是查询id小于10的所有数据。

where

在上面的案例中小伙伴们可能都发现了一个问题,就是我们在添加查询条件的时候,在查询条件之前都先添加了where 1=1,然后后面直接在这之后再追加and什么什么的,那么每次这样来写显然有点麻烦,有没有简单一点的方案呢?当然有,我们可以通过where元素,如下:

<select id="getUser3" resultMap="u"> SELECT * FROM user2 <where> <choose> <when test="id!=null"> AND id=#{id} </when> <when test="address!=null"> AND address=#{address} </when> <when test="username!=null"> AND user_name LIKE concat(#{username},'%') </when> <otherwise> AND 10>id </otherwise> </choose> </where> </select>
  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

这样,只有where元素中有条件成立,才会将where关键字组装到SQL中,这样就比前一种方式简单许多。

trim

trim有点元素替换的意思,还是上面的案例,我们可以将and替换为where,如下:

<select id="getUser4" resultMap="u"> SELECT * FROM user2 <trim prefix="where" prefixOverrides="and"> AND id=1 </trim> </select>
  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

这个最终执行的sql是SELECT * FROM user2 where id=1

set

set是我们在更新表的时候使用的元素,通过set元素,我们可以逐字段的修改一条数据,如下:

<update id="update"> UPDATE user2 <set> <if test="username!=null"> user_name=#{username}, </if> <if test="password!=null"> password=#{password} </if> </set> WHERE id=#{id} </update>
  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

在set元素中,如果遇到了逗号,系统会自动将之去除。

foreach

foreach元素用来遍历集合,比如我想查询多个城市的人,我的sql语句可能是这样SELECT * FROM user2
WHERE address IN('西安','北京')
,我在查询的时候可能只是传入了一个list集合,该集合中有西安和北京两个查询条件,那我如何将这个集合组装成一个sql语句呢?很简单,如下:

<select id="getUserInCities" resultMap="u"> SELECT * FROM user2 WHERE address IN <foreach collection="cities" index="city" open="(" separator="," close=")" item="city"> #{city} </foreach> </select>
  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

collection表示传入的参数中集合的名称,index表示是当前元素在集合中的下标,open和close则表示如何将集合中的数据包装起来,separator表示分隔符,item则表示循环时的当前元素。这样一段配置最终组合成的sql就是SELECT * FROM user2
WHERE address IN('西安','北京')

bind

使用bind元素我们可以预先定义一些变量,然后在查询语句中使用,如下:

<select id="getUserByName" resultMap="u"> <bind name="un" value="username+'%'"></bind> SELECT* FROM user2 WHERE user_name LIKE #{un} </select>
  
 
  • 1
  • 2
  • 3
  • 4
  • 5

这个貌似没什么难度,不再赘述。

以上。

本文案例下载:
本文案例GitHub地址https://github.com/lenve/JavaEETest/tree/master/Test27-mybatis9

以上。

参考资料:
《深入浅出MyBatis 技术原理与实战》第五章

文章来源: wangsong.blog.csdn.net,作者:_江南一点雨,版权归原作者所有,如需转载,请联系作者。

原文链接:wangsong.blog.csdn.net/article/details/55105400

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。