四、MyBatis 动态语句

本章概要

  • 动态语句需求和简介
  • if 和 where 标签
  • set 标签
  • trim 标签(了解)
  • choose/when/otherwise 标签
  • foreach 标签
  • sql 片段

4.1 动态语句需求和简介

经常遇到很多按照很多查询条件进行查询的情况,比如智联招聘的职位搜索等。其中经常出现很多条件不取值的情况,在后台应该如何完成最终的SQL语句呢?

四、MyBatis 动态语句_第1张图片

动态 SQL 是 MyBatis 的强大特性之一。如果你使用过 JDBC 或其它类似的框架,你应该能理解根据不同条件拼接 SQL 语句有多痛苦,例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号。利用动态 SQL,可以彻底摆脱这种痛苦。

使用动态 SQL 并非一件易事,但借助可用于任何 SQL 映射语句中的强大的动态 SQL 语言,MyBatis 显著地提升了这一特性的易用性。

如果你之前用过 JSTL 或任何基于类 XML 语言的文本处理器,你对动态 SQL 元素可能会感觉似曾相识。在 MyBatis 之前的版本中,需要花时间了解大量的元素。借助功能强大的基于 OGNL 的表达式,MyBatis 3 替换了之前的大部分元素,大大精简了元素种类,现在要学习的元素种类比原来的一半还要少。

4.2 if 和 where 标签

使用动态 SQL 最常见情景是根据条件包含 where / if 子句的一部分。比如:


<select id="selectEmployeeByCondition" resultType="employee">
  select emp_id,emp_name,emp_salary from t_emp
  
  <where>
    
    
    <if test="empName != null">
      
      or emp_name=#{empName}
    if>
    <if test="empSalary > 2000">
      or emp_salary>#{empSalary}
    if>
    
  where>
select>

4.3 set 标签


<update id="updateEmployeeDynamic">
  update t_emp
  
  
  <set>
    <if test="empName != null">
      emp_name=#{empName},
    if>
    <if test="empSalary < 3000">
      emp_salary=#{empSalary},
    if>
  set>
  where emp_id=#{empId}
  
update>

4.4 trim 标签(了解)

使用 trim 标签控制条件部分两端是否包含某些字符

  • prefix属性:指定要动态添加的前缀
  • suffix属性:指定要动态添加的后缀
  • prefixOverrides属性:指定要动态去掉的前缀,使用“|”分隔有可能的多个值
  • suffixOverrides属性:指定要动态去掉的后缀,使用“|”分隔有可能的多个值

<select id="selectEmployeeByConditionByTrim" resultType="com.atguigu.mybatis.entity.Employee">
  select emp_id,emp_name,emp_age,emp_salary,emp_gender
  from t_emp

  
  
  
  
  
  <trim prefix="where" suffixOverrides="and|or">
    <if test="empName != null">
      emp_name=#{empName} and
    if>
    <if test="empSalary > 3000">
      emp_salary>#{empSalary} and
    if>
    <if test="empAge <= 20">
      emp_age=#{empAge} or
    if>
    <if test="empGender=='male'">
      emp_gender=#{empGender}
    if>
  trim>
select>

4.5 choose/when/otherwise 标签

在多个分支条件中,仅执行一个

  • 从上到下依次执行条件判断
  • 遇到的第一个满足条件的分支会被采纳
  • 被采纳分支后面的分支都将不被考虑
  • 如果所有的 when 分支都不满足,那么就执行 otherwise 分支

<select id="selectEmployeeByConditionByChoose" resultType="com.atguigu.mybatis.entity.Employee">
  select emp_id,emp_name,emp_salary from t_emp
  where
  <choose>
    <when test="empName != null">emp_name=#{empName}when>
    <when test="empSalary < 3000">emp_salary < 3000when>
    <otherwise>1=1otherwise>
  choose>

  
select>

4.6 foreach 标签

基本用法,用批量插入举例


<foreach collection="empList" item="emp" separator="," open="values" index="myIndex">
  
  (#{emp.empName},#{myIndex},#{emp.empSalary},#{emp.empGender})
foreach>

批量更新时需要注意:
上面批量插入的例子本质上是一条SQL语句,而实现批量更新则需要多条SQL语句拼起来,用分号分开。也就是一次性发送多条SQL语句让数据库执行。此时需要在数据库连接信息的URL地址中设置:

atguigu.dev.url=jdbc:mysql:///mybatis-example?allowMultiQueries=true

对应的foreach标签如下:


<update id="updateEmployeeBatch">
  <foreach collection="empList" item="emp" separator=";">
    update t_emp set emp_name=#{emp.empName} where emp_id=#{emp.empId}
  foreach>
update>

关于foreach标签的collection属性:
如果没有给接口中List类型的参数使用@Param注解指定一个具体的名字,那么在collection属性中默认可以使用collection或list来引用这个list集合。这一点可以通过异常信息看出来:
Parameter ‘empList’ not found. Available parameters are [arg0, collection, list]
在实际开发中,为了避免隐晦的表达造成一定的误会,建议使用@Param注解明确声明变量的名称,然后在foreach标签的collection属性中按照@Param注解指定的名称来引用传入的参数。

4.7 sql 片段

抽取重复的 SQL 片段


<sql id="mySelectSql">
  select emp_id,emp_name,emp_age,emp_salary,emp_gender from t_emp
sql>

引用已抽取的 SQL 片段


<include refid="mySelectSql"/>

你可能感兴趣的:(#,MyBatis,MyBatis,动态语句,if,和,where,标签,set,标签,trim,标签,foreach,标签)