Mybatis 动态SQL

时间:2021-08-07
本文章向大家介绍Mybatis 动态SQL,主要包括Mybatis 动态SQL使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

动态 SQL

MyBatis 的核心就是能够对 SQL 语句进行灵活的操作,甚至还可以通过表达式进行判断,对 SQL 语句进行灵活 的拼装,组成最终的想要执行的 SQL,这就是动态 SQL 的含义。 例如,在进行复杂查询时,查询条件可能是多个,也可能是一个,也就是说,查询条件不确定。需要根据查询条 件,来确定最终执行的 SQL 语句。

使用 mybatis 的动态 SQL 时,需要标签元素的支持,最常用的为 where 元素和 if 元素

  • mapper.xml
<select id="queryUserByItemName" parameterType="userVo" resultType="user">
select * from user join item on user.user_id=item.user_id
<where>
<if test="item!=null and item.name!=null and item.name!=''">
and item.name=#{item.name}
</if>
<if test="cname!=null and cname!=''">
and user.cname like #{cname}
</if>
</where>
</select>

程序解析:配置动态 SQL 时,要用 where 标签转换成 where 关键字,不要把 where 关键字写死在 SQL 中,因 为如果 SQL 中的条件判断都不成立,就没有后面的过滤条件,如果 where 关键字写死在 SQL 语句中反而出错。而使 用 where 标签,由 MyBatis 框架在解析时判断是否需要在 SQL 中加入 where 关键字。 if 标签中的判断,首先判断是否不为 null,然后再判断是否不为空,判断空时使用两个单引号,并且单引号中间 不能有空格。过滤条件的拼接关键字 and、or 等一定要写死在 SQL 中,MyBatis 框架不会为 SQL 拼接 and、or 等 关键字,但是如果 where 关键字后出现了 and 或者 or 关键字,MyBatis 反而会去掉这个关键字。例如上面程序中, 第一个 if 判断成立,SQL 语句会变成 where and item.name=? ,此时 MyBatis 就会去掉这个关键字

引用 SQL 片段

在 mapper.xml 配置文件中,如果存在大量的复杂查询,而且查询条件相同,那么则可以把查询条件抽取成一个 SQL 片段,在其他 SQL中引用该片段即可。

  • mapper.xml 配置文件
<!-- 定义 SQL 片段 -->
<sql id="userQuery">
<where>
<if test="item!=null and item.name!=null and item.name!=''">
and item.name=#{item.name}
</if>
<if test="cname!=null and cname!=''">
user.cname like #{cname}
</if>
</where>
</sql>
<!-- 根据商品名称查询,引用 SQL 片段 -->
<select id="queryUserByItemName" parameterType="userVo" resultType="user">
select * from user join item on user.user_id=item.user_id
<include refid="userQuery" />
</select>

程序解析:通过 SQL 片段的定义,不仅可以减少 mapper.xml 配置文件的书写,而且方便程序人员的开发。

使用 foreach 遍历

在进行复杂 SQL 查询时,往往会遇到这样一种情况,对于某个列的值,好几个值都符合条件,使用 SQL 书写格 式如下:

where column='value1' or column='value2' or column='value3' 

执行此 SQL 时传入的参数就需要是个集合,在 MyBatis 中,对于这种情况的处理,使用 foreach 元素解决。 foreach 标签用于遍历传入的集合,属性如下:

  1. collection:指定要遍历的集合对象
  2. item:定义标识指向每次遍历时得到的对象
  3. open:开始遍历时要拼接的字符串
  4. close:结束遍历时要拼接的字符串
  5. separator:遍历两个对象中间要拼接的字符串
  • Mapper 接口定义
public List<User> queryUserByIds(List<Integer> idList);
  • mapper.xml 配置文件
<select id="queryUserByIds" parameterType="list" resultMap="userMap">
select * from user
<where>
<foreach collection="list" item="value" separator=" or ">
user_id=#{value}
</foreach>
</where>
</select>
  • 测试程序:
@Test
public void testQueryUserByIds() throws Exception{
List<Integer> idList = new ArrayList<>();
idList.add(13);
idList.add(14);
idList.add(15);
UserMapper mapper = session.getMapper(UserMapper.class);
List<User> userList = mapper.queryUserByIds(idList);
for (User userObj : userList) {
System.out.println(userObj.getCname());
}
}

程序解析:如果 List 集合中不存在元素,上面 mapper.xml 配置文件中定义的 foreach 则不会执行,最终执行 的 SQL 为:select * from user。对上面的 SQL 进行更改为另一种格式,使用 in的方式 如下图所示:

  • mapper.xml 配置文件
<select id="queryUserByIds" parameterType="list" resultMap="userMap">
select * from user
<where>
<foreach collection="list" item="value" open="user_id in (" separator="," close=")">
#{value}
</foreach>
</where>
</select>

测试程序同上。

原文地址:https://www.cnblogs.com/LiPengFeiii/p/15111519.html