一、动态sql
使用jdbc或者其他框架,很多时候需要去拼装sql,这是一个麻烦的事情。
例如:一个多筛选条件的页面,需要根据筛选的条件去查询所符合条件的数据,使用hibernate需要在类中一个个条件的去判断,来选择sql拼装,由于是在类中当新增筛选条件时需要去类中修改并且重新编译方可生效。
而mybatis提供对sql 语句动态的组装能力,而且它只有几个基本元素,十分简单明了,大量的判断都可以在mybatis的映射xml文件里面配置,以达到许多我们需要大量代码才能实现的功能,大大减少了我们编写代码的工作量,这体现了mybatis的灵活性高度可配置和可维护性。
mybatis也可以在注解中配置sql,但是由于注解中配置功能受限,对于复杂的sql而言可读性很差,所以使用较少,并且使用注解的方式sql是写在java类中,每次修改都需要编译。
二、mybatis元素介绍与使用
mybatis中有哪些元素?
元素:if 、choose when otherwise 、trim 、foreach 、where 、set 、bind
属性: test
下面就来一 一介绍这些元素的作用
- if 元素
是最常用的元素,用于判断语句,相当于java中的if效果,只不过没有else。它常常与test属性结合在一起使用,可以多个if结合在一起使用。
<!--1. if 判断是否符合条件,一个sql中可以使用多个if判断 -->
<select id="queryStudentAll" parameterType="student" resultType="student">
select * from student
where 1=1
<!--每个if判断一个参数值,符合条件的则拼装sql -->
<if test="stuName != null and stuName != ''">
and stu_name = #{stuName}
</if>
<if test="age != null">
and age > #{age}
</if>
</select>
缺点: 需要手动在动态sql前面写上一个 where 1=1 条件
- choose when otherwise
这个就相当于java中的 switch case 效果一样。当所有条件不满足时需要有一个默认条件
<!--2. choose when otherwise
类似于: switch case defaule
从上至下选择最早满足的条件,只选择一个条件
-->
<select id="queryStudentChoose" parameterType="student" resultType="student">
select * from student where 1=1
<choose>
<when test="grade != null and grade != ''">
and grade = #{grade}
</when>
<when test="email != null and email != '' ">
and email like '%${email}%'
</when>
<otherwise>
and id > 2 <!--当所有条件不满足时,走此默认条件 -->
</otherwise>
</choose>
</select>
缺点:同 if 需要在前面手动添加一个 where条件。
注:只有一个条件会生效
- where 元素
由于上面的两种元素都需要在前面添加一个默认的where 条件,避免这种情况所有有了where元素,可以结合多种元素一起使用,在where元素内 alt+/ 会有提示
<!--3. where:如上语句不想在后面加上 where 1=1 ,则使用下面写法,where/if -->
<select id="queryStudentWhere" parameterType="student" resultType="student">
select * from student
<where>
<if test="email != null and email != ''">
and email like '%${email}%'
</if>
<if test="grade != null and grade != ''">
and grade = #{grade}
</if>
</where>
</select>
- trim 元素
<!--4. trim 效果与 where类似
prefix 前缀
prefixOverrides 假如条件第一个词满足则清除
如下两个条件都满足时: and email like '%${email}%' and grade = #{grade},第一个词and符合条件-清除
-->
<select id="queryStudentTrim" parameterType="student" resultType="student">
select * from student
<trim prefix="where" prefixOverrides="and" >
<if test="email != null and email != ''">
and email like '%${email}%'
</if>
<if test="grade != null and grade != ''">
and grade = #{grade}
</if>
</trim>
</select>
- set元素
这个元素用于更新操作,当然trim也可以完成这个操作
<!--5. set:修改数据,在hibernate中修改数据会把每个字段都更新,比较笨重,mybatis就比较轻量,判断符合条件的字段才会更新。 -->
<update id="updateStudentInfo" parameterType="student" >
update student
<set>
<if test="stuName != null and stuName != ''">
stu_name=#{stuName},
</if>
<if test="age != null">
age=#{age},
</if>
<if test="email != null and email != ''">
email=#{email},
</if>
<if test="grade != null and grade != ''">
grade=#{grade}
</if>
</set>
where id=#{id}
</update>
<!-- <update id="">
update student
<trim prefix="set" suffixOverrides=",">
<if test="stuName != null and stuName != ''">
stu_name=#{stuName},
</if>
<if test="age != null">
age=#{age},
</if>
<if test="email != null and email != ''">
email=#{email},
</if>
<if test="grade != null and grade != ''">
grade=#{grade},
</if>
</trim>
where id=#{id}
</update> -->
- foreach 元素
用于处理参数是集合、数组类型的数据
<!--6. foreach: 遍历取出集合中的参数
collection:参数集合名
item : 遍历后的每个参数
index :当前参数角标
separator:多个参数间的分割符
open:前缀
close:后缀
#{item}:遍历取出的每个参数值
完整遍历后的参数示例:(1,2,3) ->
select * from student where id in (1,2,3)
-->
<select id="queryStudentInfoByIn" parameterType="int" resultType="student">
select * from student where id in
<foreach collection="list" item="item" index="index" separator="," open="(" close=")">
#{item}
</foreach>
</select>
<!--批量插入-->
<insert id="saveBath" resultType="student">
insert into student(stu_name,age)
values
<foreach coolection="list" item="item" separator=",">
(#{item.id},#{item.stuName})
</foreach>
</insert>
- bind 元素
用于处理参数,为参数添加一些修饰
<!--7. bind : -->
<select id="queryStudentInfoByBind" parameterType="student" resultType="student">
<bind name="pattern" value="'%' + email + '%'"/>
select * from student where email like #{pattern}
</select>
注意bind标签中参数不是 #{email } 这么取得,直接属性名就可 email
一般不会这么使用bind元素来达到上面的效果,上面主要是用于 拼接 %%
示例一: $ 处理,$不会预编译参数,会直接去参数字面值
<if test="email != null and email != ''">
and email like '%${email}%'
</if>
如下日志,发现并没有为email参数占位符? ,而是直接取值拼装
2019-07-31 15:53:46 DEBUG mybatis.sql.com.cjy.mybatis.dao.StudentMapper.queryStudentWhere - ==> Preparing: select * from student WHERE email like '%xiaoming%' and grade = ?
示例二: || 拼接
<select id="queryPersonByIdAndLikeNames" resultMap="baseResult" >
select <include refid="baseColumns"/>
from person where id = #{id} and user_name like '%' || #{userName}
</select>
示例三:使用concat函数处理
<if test="email != null and email != ''">
and email like concat('%' ,#{email} ,'%')
</if>
注意:上面几种拼接sql %% 的方式需要注意使用的数据库。
优势:当一张表有特别多的字段时,我们只需要更新其中的某几个字段,使用hibernate框架的话由于映射关系会更新所有字段。
mybatis就不一样,有了动态sql的拼接,只需要更新其中满足条件的值即可。
demo地址 : https://github.com/chenjy512/mybatis-demo/tree/master/source-mybatis-05dynamic_SQL