动态SQL
动态SQL:根据查询条件,动态生成SQL
动态标签: if, choose ,trim, foreach
<if test="OGNL"/> test判断表达式, 从参数中取值进行判断,遇到特殊字符,使用转义字符,
<select id="getEmployee" resultType="com.dong.service.employee" databaseId="mysql" >
select * from Blog where
<if test="id != null">
id = #{id}
</if>
<if test="last_name != null">
and lastname = #{lastName}
</if>
</select>
当拼装SQL查询条件时,如果某些情况出错,eg:直接where 后结and,(上面的例子中的id条件不成立) 这种情况下,则需要处理:
1,在SQL前加一个真值 判断条件 : 1 = 1 ,
2.Mybatis 可使用<where> 标签,将所有的查询条件包含在内即可,Mybatis会将SQL中多出来的and ,or 去掉 , where 只会去掉第一个多出来的and 或者or,
<select id="getEmployee" resultType="com.dong.service.employee" databaseId="mysql" >
select * from Blog
<where>
<if test="id != null">
id = #{id}
</if>
<if test="last_name != null">
and lastname = #{lastName}
</if>
</where>
</select>
3.trim 标签,当SQL语句后面多出一个or ,and ,则可以使用trim 标签:
prefix: 前缀, trim标签体中是整个字符串拼接后的结果, prexfix 给拼接后的整个字符串一个前缀,
prefixOverrides: 前缀覆盖,去掉整个字符串前面多余的字符,
suffix: 后缀,给拼接后的字符串加后缀,
suffixOverrides: 后缀覆盖,去掉整个字符串后面多余的字符,
<select id="getEmployee" resultType="com.dong.service.employee" databaseId="mysql" >
select * from Blog
<trim prefix="where" suffixOverrides="and">
<if test="id != null">
id = #{id} and
</if>
<if test="last_name != null">
lastname = #{lastName} and
</if>
<if test="first_name != null">
first_name = #{firstName}
</if>
</trim>
</select>
choose: 分支选择,,类似与switch,
<select id="getEmployees" resultType="com.dong.service.employee">
select * from BLog where
<choose>
<when test="id != null">
id = #{id}
</when>
<when test="last_name != null">
last_name= #{lastName}
</when>
<otherwise>
gender = 1
</otherwise>
</choose>
</select>
当有多个分支,则选择第一个,当没有条件满足,则选择otherwise,
trim:where标签 和 set标签
where用来封装查询条件, set 封装修改条件, eg:
<update id="updateEmployee" parameterType="com.dong.service.employee">
update tbl_employee set
<if test="lastname != null">
lastname=#{lastName},
</if>
<if test="email != null">
email=#{email}
</if>
</update>
当email为空时,执行出错,因为会多出多余的逗号,可使用set标签将其包含,自动去掉逗号,
<update id="updateEmployee" parameterType="com.dong.service.employee">
update tbl_employee
<set>
<if test="lastname != null">
lastname=#{lastName},
</if>
<if test="email != null">
email=#{email}
</if>
</set>
</update>
注意:也可使用trim标签,时候后缀参数,去掉逗号,
foreach:
collection:指定遍历集合, list类型的参数会特殊封装到Map中,Map的key就叫list,
item:将当前遍历的元素赋值给指定的变量, #{变量名}就可以取出变量的值,
separator: 元素的分隔符,
open:遍历所有结果,拼接一个开始的字符,
close:遍历所有结果,拼接一个结束字符
index:索引,遍历list的时候的索引,item就是当前值,
遍历Map的时候,则index则表示key, item就是Map的值,
<select id="getEmployee2" resultType="com.dong.service.employee">
select * from BLog where id in
<foreach collection="ids" item="vids" separator="," open="(" close=")">
#{vids}
</foreach>
</select>
批量插入
1.利用foreach循环插入的值
<insert id="addEmployee" parameterType="com.dong.service.employee" useGeneratedKeys="true" keyProperty="id">
insert into tbl_employee(last_name,email,gendar) values
<foreach collection="emps" item="emp" separator=",">
(#{emp.id},#{emp.firstname},#{emp.lastname})
</foreach>
</insert>
2.利用foreach循环执行语句
<delete id="deleteEmployee" >
<foreach collection="emps" item="emp" separator=",">
delete from tbl_employee where id = #{emp.id}
</foreach>
</delete>
在这里使用删除语句,如果是想插入语句,需设置mySQL属性, allowMultiQueries = true; 可以用于其他的批量操作,批量删除,批量修改,
Oracle数据库批量操作:(同Mysql一个实现原理,之不过需要修改SQL语句)
Oracle不支持values(),(),(),..
1.Oracle支持的批量方式: 1.多个insert放到begin - end 之间,2.利用中间表,实现方式,
<insert id = "addemp" databaseId= "oracle">
<foreach collection ="emps" item ="emp" open = "begin" close= " end;" > insert into table_name (last_name,email,gender,d_id) values
( employee_seq.nextval,#{emp.lastname},#{emp.email},#{emp.gender},#{emp.d_id})
</foreach>
</insert>
内置参数
Mybatis:默认两个参数:
_parameter:代表整个参数, 单个参数, _parameter 就是这个参数,如果多个,则被封装为Map,
_databaseId:如果配置了databaseIdProvider标签, , _databaseId就代表当前数据库的别名,
注意:
bind标签
value:为绑定的值, name:名,value中可以写OGNL表达式.
<bind name = "_lastname" value = "'%'+lastName+'%'"/>
在sql语句中使用%#{}%是不可以实现拼接,使用%$%可以.
sql标签
抽取重用的SQL片段,方便后面使用
<sql id="insertCloumn" >(id,name,gender)</sql>
再select,insert,update等语句中可引用,通过<include ></include>引入即可.
<insert id="addEmployee" parameterType="com.dong.service.employee" useGeneratedKeys="true" keyProperty="id">
insert into tbl_employee
<include refid="insertCloumn"></include>
values
<foreach collection="emps" item="emp" separator=",">
(#{emp.id},#{emp.firstname},#{emp.lastname})
</foreach>
</insert>
include还可以自定义一些propery, <sql>标签内部就可使用自定义的属性,注意:include 使用${prop}取值, ,#{不可用},
注意,bind标签内部也可以进行判断.
Mybatis缓存机制
默认两级缓存
一级缓存:本地缓存, 一级缓存默认是一直开的,与数据库同一次会话期间查询的数据会被放入到本地缓存中,以后如果想要获取相同的数据,直接从缓存中拿,没必要在去数据库查.
一级缓存失效:
1.SQLSession不同,因为一级缓存是session级别,只在同一个会话中有效,
2.如果session相同,查询条件不同,则当然不会相同,因为当前session没有,所以自然会在重新查询
3.SQLSession相同,两次查询之间进行了增删改,(这次增删改有可能改变查询数据)
4.SQLSession相同,但是手动清除一级缓存,
二级缓存(全局缓存): 基于namespace的级别的缓存,一个namespace对应一个二级缓存,
工作机制:
1.一个会话,查询一条数据,数据被放到一级缓存
2.如果会话关闭,一级缓存中的数据会被保存到二级缓存,新的会话,参考二级缓存,不同namespace查询的数据会放到自己对应的缓存中.
......
如有异议,敬请指出,谢谢观看,与君共勉.(观看https://www.bilibili.com/video/av45816095?t=113&p=36)