#MyBatis的动态SQL
一回顾动态一词
- 动态页面和静态页面*动态页面:有数据交互的页面(用于| 如果| …)
二动态SQL简介
- .OGNL :(对象图导航语言),对象图导航语言,是这一种强大的表达式语言,通过它可以非常方便的来操作对象属性.-动态SQL是MyBatis的的的的的的的的的的的强大的特性:一个极大的支持类似jstl中的各种流程控制语句。如下: *如果 *选择 * foreach * trim * …
三Mybatis动态SQL详解
- \ <其中>:去掉其中关键字后面第一个和|或。-\ <如果测试=“ OGNL表达语言”>:流程控制的简单判断(分支)语句-\ <装饰>:为SQL语句添加或删除指定的字符(前|后) *前缀:添加前缀 *前缀覆盖:删除前缀 后缀:添加后缀后缀覆盖:删除后缀-\ <集>:在修改语句中,去掉SQL语句中多出的一个“”-\ <选择>:主要是用于分支判断,某些java的中的开关的情况下,只会满足所有分支中的一个-
1. 循环迭代元素
<select id="getEmpsByIds" resultType="com.atguigu.dynamicsql.bean.Employee">
SELECT id,last_name,email,gender
WHERE id IN
<foreach collection="ids" item="id" separator="," open="(" close=")">
#{id}
</foreach>
</select>
2. 批处理新增
<insert id="batchInsertEmp" >
<foreach collection="emps" item="emp">
INSERT INTO tbl_employee(last_name,email,gender)
VALUES(#{emp.lastName},#{emp.email},#{emp.gender});
</foreach>
</insert>
<insert id="batchInsertEmp" >
INSERT INTO tbl_employee(last_name,email,gender)
VALUES
<foreach collection="emps" item="emp" separator=",">
(#{emp.lastName},#{emp.email},#{emp.gender})
</foreach>
</insert>
<sql>:定义重复多次的sql片段
<sql id="select_employee">
SELECT id,last_name,email,gender
FROM tbl_employee
</sql>
- 使用:<include refid="select_employee"/>引入sql片段。
- 使用特殊字符时,建议使用<![CDATA[ ... ]]>如下处理:
<sql id="select_employee">
<![CDATA[
SELECT id,last_name,email,gender
FROM tbl_employee
]]>
</sql>
Mapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--映射文件的根标签
-->
<mapper namespace="com.atguigu.mybatis.mapper.EmployeeMapper">
<select id="getEmpByEmp" resultType="com.atguigu.dynamicsql.bean.Employee">
select id,last_name,email,gender
from tbl_employee
<where>
<if test="id != null">
and id=#{id}
</if>
<if test="lastName!=null && !"".equals(lastName)">
AND last_name=#{lastName}
</if>
<if test="email!=null and email.trim()!=''">
AND email=#{email}
</if>
<if test=""男".equals(gender) or "女".equals(gender)">
AND gender=#{gender}
</if>
</where>
</select>
<select id="getEmpByTrim" resultType="com.atguigu.dynamicsql.bean.Employee">
select id,last_name,email,gender
from tbl_employee
<trim prefix="where" suffixOverrides="and|or">
<if test="id!=null">
id=#{id} AND
</if>
<if test="lastName!=null && !"".equals(lastName)">
last_name=#{lastName} AND
</if>
<if test="email!=null and email.trim()!=''">
email=#{email} AND
</if>
<if test=""男".equals(gender) or "女".equals(gender)">
gender=#{gender} AND
</if>
</trim>
</select>
<!-- 实现修改Employee信息(set)-->
<update id="updateEmployee">
UPDATE tbl_employee
<set>
<if test="lastName!=null">
last_name=#{lastName},
</if>
<if test="email!=null">
email=#{email},
</if>
<if test="gender!=null">
gender=#{gender},
</if>
</set>
WHERE id=#{id}
</update>
<!-- 按条件查询员工信息,(不确定的一个条件)-->
<!-- Choose-->
<select id="getEmpByChoose" resultType="com.atguigu.dynamicsql.bean.Employee">
SELECT id,last_name,email,gender
FROM tbl_employee
<where>
<choose>
<when test="id!=null">
id=#{id}
</when>
<when test="lastName!=null">
last_name=#{lastName}
</when>
<when test="email!=null">
email=#{email}
</when>
<otherwise>
gender=#{gender}
</otherwise>
</choose>
</where>
</select>
<sql id="column_emp" >
id,last_name,email,gender
</sql>
<sql id="select_emp" >
select id,last_name,email,gender
from tbl_employee
</sql>
<select id="getEmpsByIds" resultType="com.atguigu.dynamicsql.bean.Employee">
<include refid="select_emp"/>
where id in
<foreach collection="ids" item="id" separator="," open="(" close=")">
#{id}
</foreach>
</select>
<!-- <insert id="batchInsertEmp">-->
<!-- <foreach collection="emps" item="emp">-->
<!-- insert into tbl_employee(last_name,email,gender)-->
<!-- values(#{emp.lastName},#{emp.email},#{emp.gender});-->
<!-- </foreach>-->
<!-- </insert> -->
<insert id="batchInsertEmp">
insert into tbl_employee(last_name,email,gender)
values
<foreach collection="emps" item="emp" separator=",">
(#{emp.lastName},#{emp.email},#{emp.gender})
</foreach>
</insert>
</mapper>
Mybatis中缓存
三级缓存jar
一 为什么使用缓存
- 生活中,缓存视频、音频的好处:省钱、速度快
- 程序中,使用缓存:节约资源、速度快。
二 Mybatis的几种缓存
-
一级缓存
- 默认开启
- 也叫SqlSession级别缓存(本地缓存)
- 缓存机制
- 基于相同SqlSession,多次查询相同数据。每次查询都会优先从缓存中获取数据,
- 如果缓存中没有取到需要的数据,则从数据库(或目标资源)中获取数据。之后,
将数据存放到一级缓存中。 - 如果从缓存中获取的目标数据,则无需从数据库(或目标资源)中检索数据。
-
一级缓存关闭&失效问题
- 一级缓存不能关闭,只能清空【clearCache()】。
- 一级缓存主要有以下四种失效方式
- 【不同的SqlSession】对应不同的一级缓存
- 同一个SqlSession但是【查询条件】不同
- 同一个SqlSession两次查询期间执行了任何一次【增删改操作】
- 因为:增删改操作,默认会清空缓存。
4.同一个SqlSession两次查询期间【手动清空】了缓存
- 因为:增删改操作,默认会清空缓存。
-
二级缓存
- 默认关闭,使用之前,需要手动开启二级缓存。
- 也叫namespace级别缓存(sqlSessionFactory级别)
- 二级缓存使用的步骤:
1.全局配置文件中开启二级缓存
2.需要使用二级缓存的映射文件处使用cache配置缓存
3.注意:POJO需要实现Serializable接口
-
二级缓存相关属性【标签中的属性】
- eviction:设置缓存的回收策略
- LRU:最近最少使用的先回收
- FIFO:先进先出
- flushInternal:刷新的时间间隔,单位毫秒。
- size:设置缓存的最大对象数量,正整数。
- readOnly:设置缓存是否为只读。
- type:引入第三方缓存类库时,使用。
- eviction:设置缓存的回收策略
-
二级缓存的缓存机制(重要)
- 基于相同的SqlSessionFactory ,多次查询相同数据。优先从二级缓存中获取数据。
- 如果从二级缓存中未取到数据,再去一级缓存中获取数据。
- 从一级缓存中也未获取到数据,则从数据库中获取数据,
之后优先存放一级缓存,【提交或关闭sqlSession时,才将一级缓存中的数据,
存放到二级缓存中。】
- 基于相同的SqlSessionFactory ,多次查询相同数据。优先从二级缓存中获取数据。
-
第三方缓存(EhCache)
- EhCache:进程内的缓存框架。
- 使用步骤
1. 导入4个jar包
2. 编写核心配置文件(ehcache.xml)
3. 在映射文件中添加
4. 必须开启二级缓存 - 扩展
- 如何局部关闭二级缓存
- 在指定的sql标签(select),useCache=“false”;
- 对于增删改操作:flushCache=“true”,代表执行增删改后默认刷新缓存。
ehcache.xml
<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">
<!-- 磁盘保存路径 -->
<diskStore path="D:\1SGGJava\ehcache" />
<defaultCache
maxElementsInMemory="1000"
maxElementsOnDisk="10000000"
eternal="false"
overflowToDisk="true"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU">
</defaultCache>
</ehcache>
<!--
属性说明:
l diskStore:指定数据在磁盘中的存储位置。
l defaultCache:当借助CacheManager.add("demoCache")创建Cache时,EhCache便会采用<defalutCache/>指定的的管理策略
以下属性是必须的:
l maxElementsInMemory - 在内存中缓存的element的最大数目
l maxElementsOnDisk - 在磁盘上缓存的element的最大数目,若是0表示无穷大
l eternal - 设定缓存的elements是否永远不过期。如果为true,则缓存的数据始终有效,如果为false那么还要根据timeToIdleSeconds,timeToLiveSeconds判断
l overflowToDisk - 设定当内存缓存溢出的时候是否将过期的element缓存到磁盘上
以下属性是可选的:
l timeToIdleSeconds - 当缓存在EhCache中的数据前后两次访问的时间超过timeToIdleSeconds的属性取值时,这些数据便会删除,默认值是0,也就是可闲置时间无穷大
l timeToLiveSeconds - 缓存element的有效生命期,默认是0.,也就是element存活时间无穷大
diskSpoolBufferSizeMB 这个参数设置DiskStore(磁盘缓存)的缓存区大小.默认是30MB.每个Cache都应该有自己的一个缓冲区.
l diskPersistent - 在VM重启的时候是否启用磁盘保存EhCache中的数据,默认是false。
l diskExpiryThreadIntervalSeconds - 磁盘缓存的清理线程运行间隔,默认是120秒。每个120s,相应的线程会进行一次EhCache中数据的清理工作
l memoryStoreEvictionPolicy - 当内存缓存达到最大,有新的element加入的时候, 移除缓存中element的策略。默认是LRU(最近最少使用),可选的有LFU(最不常使用)和FIFO(先进先出)
-->
** Mapper.xml **
的xml <! -配置二级缓存- > <缓存驱逐=“FIFO” flushInterval =“600000”的大小=“500” readOnly的=“假”> </缓存>