您的位置:首页 > 数据库

MyBatis-动态SQL

2018-09-24 11:37 375 查看

目录

一、概述

二、if

1.格式

2.实例

三、choose(when,otherwise)

1.格式

2.实例

四、trim(where,set)

1.where

2.trim

3.set

五、foreach

1.in(x,y,z...)条件查询

2.批量保存

六、bind

七、可重用的sql片段

八、多数据库支持

一、概述

  • 动态SQL是MyBatis的强大特性之一。极大的简化了我们拼装SQL的操作

  • 动态SQL元素和使用JSTL或其它类似的基于XML的文本处理器类似

  • MyBatis采用功能强大的基于OGNL的表达式来简化操作

    if

  • choose(when,otherwise)

  • trim(where,set)

    foreach

二、if

1.格式

[code]<if test=""></if>

2.实例

[code]<!-- 查询员工,要求,携带了哪个字段查询条件就带上这个字段的值 -->
<!-- public List<Employee> getEmpsByConditionIf(Employee employee); -->
<select id="getEmpsByConditionIf" resultType="com.itheima.domain.Employee">
select * from tbl_employee
<!-- where -->
<where>
<!-- test:判断表达式(OGNL)
OGNL参照PPT或者官方文档。
c:if  test
从参数中取值进行判断

遇见特殊符号应该去写转义字符:
&&:
-->
<if test="id!=null">
id=#{id}
</if>
           <!-- &amp为& &quot为'-->
<if test="lastName!=null &amp;&amp; lastName!=&quot;&quot;">
and last_name like #{lastName}
</if>
<if test="email!=null and email.trim()!=&quot;&quot;">
and email=#{email}
</if>
<!-- ognl会进行字符串与数字的转换判断  "0"==0 -->
<if test="gender==0 or gender==1">
and gender=#{gender}
</if>
</where>
</select>

三、choose(when,otherwise)

1.格式

[code]<choose>
<when test=""></when>
   <when test=""></when>
<otherwise></otherwise>
</choose>

2.实例

[code]<!-- public List<Employee> getEmpsByConditionChoose(Employee employee); -->
<select id="getEmpsByConditionChoose" resultType="com..itheima.domain.Employee">
select * from tbl_employee
<where>
<!-- 如果带了id就用id查,如果带了lastName就用lastName查,都不带就查询gender=0的所有数据;只会进入其中一个 -->
<choose>
<when test="id!=null">
id=#{id}
</when>
<when test="lastName!=null">
last_name like #{lastName}
</when>
<otherwise>
gender = 0
</otherwise>
</choose>
</where>
</select>

四、trim(where,set)

1.where

​ 在使用if表达式进行查询时,有可能会发生一个问题。

[code]<select id="findActiveBlogLike"
    resultType="Blog">
SELECT * FROM BLOG
WHERE
 <if test="state != null">
   state = #{state}
 </if>
 <if test="title != null">
   AND title like #{title}
 </if>
 <if test="author != null and author.name != null">
   AND author_name like #{author.name}
 </if>
</select>

如果这些条件都没能匹配上,最终的SQL语句会变成:

[code]SELECT * FROM BLOG  
WHERE

如果仅仅第二个条件匹配成功,最终的SQL语句会变成:

[code]SELECT * FROM BLOG
WHERE
AND title like ‘someTitle’

这时,就可以使用where标签来处理上述问题

[code]<select id="findActiveBlogLike"
    resultType="Blog">
SELECT * FROM BLOG
 <where>
   <if test="state != null">
        state = #{state}
   </if>
   <if test="title != null">
       AND title like #{title}
   </if>
   <if test="author != null and author.name != null">
       AND author_name like #{author.name}
   </if>
 </where>
</select>

​ where元素只会在至少有一个子元素的条件返回 SQL 子句的情况下才去插入“WHERE”子句。而且,若语句的开头为“AND”或“OR”,where 元素也会将它们去除。

2.trim

​ 我们也可以用自定义trim元素来定制where元素的功能。

[code]<!--
prefix给拼串后的整个字符串加一个前缀
prefixOverrides="":
前缀覆盖: 去掉整个字符串前面多余的字符
suffix="":后缀
suffix给拼串后的整个字符串加一个后缀
suffixOverrides=""
后缀覆盖:去掉整个字符串后面多余的字符
-->
<trim prefix="WHERE" prefixOverrides="AND |OR ">
...
</trim>

3.set

  • set元素可以用于动态包含需要更新的列,而舍去其它的

[code]<update id="updateAuthorIfNecessary">
update Author
   <set>
     <if test="username != null">username=#{username},</if>
     <if test="password != null">password=#{password},</if>
     <if test="email != null">email=#{email},</if>
     <if test="bio != null">bio=#{bio}</if>
   </set>
where id=#{id}
</update>

​ 这里,set 元素会动态前置 SET 关键字,同时也会删掉无关的逗号,因为用了条件语句之后很可能就会在生成的 SQL 语句的后面留下这些逗号。

​ set元素的底层为:

[code]<trim prefix="SET" suffixOverrides=",">
...
</trim>

五、foreach

1.in(x,y,z...)条件查询

[code]<!--
collection:指定要遍历的集合:
list类型的参数会特殊处理封装在map中,map的key就叫list
item:将当前遍历出的元素赋值给指定的变量
separator:每个元素之间的分隔符
open:遍历出所有结果拼接一个开始的字符
close:遍历出所有结果拼接一个结束的字符
index:索引。遍历list的时候是index就是索引,item就是当前值
     遍历map的时候index表示的就是map的key,item就是map的值

#{变量名}就能取出变量的值也就是当前遍历出的元素
-->
<!--public List<Employee> getEmpsByConditionForeach(@Param("ids") List<Integer> ids);  -->
   <select id="getEmpsByConditionForeach" resultType="com.itheima.domain.Employee">
       SELECT *
       FROM tb1_employee
       WHERE id IN
       <foreach collection="ids" close=")"  separator="," item="items" open="(" >
         #{items}
       </foreach>
   </select>

2.批量保存

[code]  <!-- 批量保存 -->
<!--public void addEmps(@Param("emps")List<Employee> emps);  -->
<!--MySQL下批量保存:可以foreach遍历   mysql支持values(),(),()语法-->
<insert id="addEmps">
     INSERT INTO tb1_employee(NAME,gender,email,did)
     VALUES
     <foreach collection="emps" item="items" separator="," >
       (#{items.name},#{items.gender},#{items.email},#{items.dept.id})
     </foreach>
   </insert>

六、bind

  • bind元素可以从OGNL表达式中创建一个变量并将其绑定到上下文。

[code]<!--public List<Employee> getEmpsTestInnerParameter(Employee employee);  -->
<select id="getEmpsTestInnerParameter" resultType="com.itheima.domain.Employee">
 <bind name="_name" value="'%' + name + '%'" />
SELECT * FROM BLOG
WHERE title LIKE #{_name}
</select>
<!--可以对传过来的Employee的name参数直接进行模糊查询而不需要自己加% -->

七、可重用的sql片段

[code]!--
抽取可重用的sql片段。方便后面引用
1、sql抽取:经常将要查询的列名,或者插入用的列名抽取出来方便引用
2、include来引用已经抽取的sql:
3、include还可以自定义一些property,sql标签内部就能使用自定义的属性
-->
 <sql id="insertColumn">
<if test="_databaseId=='oracle'">
employee_id,last_name,email
</if>
<if test="_databaseId=='mysql'">
last_name,email,gender,d_id
</if>
 </sql>

<insert id="addEmps" databaseId="mysql">
insert into tbl_employee(
<include refid="insertColumn"></include>
)
values
<foreach collection="emps" item="emp" separator=",">
(#{emp.lastName},#{emp.email},#{emp.gender},#{emp.dept.id})
</foreach>
</insert>
[code]<sql id="columns">
#{profix}.id,#{profix}.name,#{profix}.age
</sql>

<select id="getUser">
select
<include refid="columns">
<property name="prefix" value="u" />
</include>
from user u where r.id=#{id}
</select>

八、多数据库支持

​ 一个配置了“_databaseId”变量的 databaseIdProvider 可用于动态代码中,这样就可以根据不同的数据库厂商构建特定的语句。

[code]<insert id="insert">
 <selectKey keyProperty="id" resultType="int" order="BEFORE">
   <if test="_databaseId == 'oracle'">
     select seq_users.nextval from dual
   </if>
   <if test="_databaseId == 'db2'">
     select nextval for seq_users from sysibm.sysdummy1"
   </if>
 </selectKey>
insert into users values (#{id}, #{name})
</insert>

 

阅读更多
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: