Mybatis快速入门(4)
CSDN话题挑战赛第2期
参赛话题:学习笔记
学习之路,长路漫漫,需要您的陪伴。
关注一波,您的关注是我最大的动力。
Mybatis
这篇文章Mybatis快速入门(1)我们介绍了快速掌握Mybatis进行简单CRUD
这篇文章Mybatis快速入门(2)我们介绍了传参以及Mybatis的各种查询。
这篇文章Mybatis快速入门(3)我们介绍了使用Mybatis进行多表查询。
本篇文章,我们介绍一下Mybatis的动态Sql技术和Mybatis的缓存机制。
一、 动态SQL
Mybatis框架的动态SQL技术是一种根据特定条件动态拼装SQL语句的功能,它存在的意义是为了解决
拼接SQL语句字符串时的痛点问题,主要是介绍标签代替sql语句,更加的灵活。
先给出总的接口写法:
public interface DynamicSQLMapper {
/*
* 多条件查询
*/
List<Emp> getEmpByCondition(Emp emp);
/*
* 测试choose when otherwise
*/
List<Emp> getEmpByChoose(Emp emp);
/*
* 通过数组实现批量删除
*/
int deleteMoreByArray(@Param("eids") Integer[] eids);
}
1. if
if标签可通过test属性的表达式进行判断,若表达式的结果为true,则标签中的内容会执行;反之标签中的内容不会执行
<select id="getEmpByCondition" resultType="Emp">
select * from t_emp where 1=1 (没有1=1的话where和and直接连接会报错)
<if test="empName!=null and empName!=''">
and emp_name = #{empName}
</if>
<if test="age!=null and age!=''">
and age = #{age}
</if>
<if test="sex!=null and sex!=''">
and sex = #{sex}
</if>
<if test="email!=null and email!=''">
and email = #{email}
</if>
</select>
2. where
<select id="getEmpByCondition" resultType="Emp">
select * from t_emp
<where>
<if test="empName!=null and empName!=''">
and emp_name = #{empName}
</if>
<if test="age!=null and age!=''">
and age = #{age}
</if>
<if test="sex!=null and sex!=''">
and sex = #{sex}
</if>
<if test="email!=null and email!=''">
and email = #{email}
</if>
</where>
</select>
where和if一般结合使用:
a>若where标签中的if条件都不满足,则where标签没有任何功能,即不会添加where关键字
b>若where标签中的if条件满足,则where标签会自动添加where关键字,并将条件最前方多余的
and去掉
注意:where标签不能去掉条件最后多余的and
3. trim
<select id="getEmpByCondition" resultType="Emp">
select <include refid="empColumns"></include> from t_emp
<trim prefix="where" suffixOverrides="and|or">
<if test="empName!=null and empName!=''">
emp_name = #{empName} and
</if>
<if test="age!=null and age!=''">
age = #{age} and
</if>
<if test="sex!=null and sex!=''">
sex = #{sex} or
</if>
<if test="email!=null and email!=''">
email = #{email} and
</if>
</trim>
</select>
trim用于去掉或添加标签中的内容
常用属性:
prefix:在trim标签中的内容的前面添加某些内容
prefixOverrides:在trim标签中的内容的前面去掉某些内容
suffix:在trim标签中的内容的后面添加某些内容
suffixOverrides:在trim标签中的内容的后面去掉某些内容
前三种sql标签可以用以下例子测试:
@Test
public void testgetEmpByCondition() {
SqlSession sqlSession = SqlSessionUtils.getSqlSession();
DynamicSQLMapper mapper = sqlSession.getMapper(DynamicSQLMapper.class);
List<Emp> list = mapper.getEmpByCondition(new Emp(null, "李四", 21, "男", "123@qq.com"));
System.out.println(list);
}
4.choose.when.otherwise
choose、when、otherwise相当于if…else if…else
<!--List<Emp> getEmpByChoose(Emp emp);-->
<select id="getEmpByChoose" resultType="Emp">
select * from t_emp
<where>
<choose>
<!--when相当于if,一个成立其他的标签就都不执行了,otherwise相当于最后一个else-->
<when test="empName!=null and empName!=''">
emp_name = #{empName};
</when>
<when test="age!=null and age!=''">
age = #{age};
</when>
<when test="sex!=null and sex!=''">
sex = #{sex};
</when>
<when test="email!=null and email!=''">
email = #{email};
</when>
<otherwise>
did = 1;
</otherwise>
</choose>
</where>
</select>
测试:
@Test
public void testGetEmpByChoose() {
SqlSession sqlSession = SqlSessionUtils.getSqlSession();
DynamicSQLMapper mapper = sqlSession.getMapper(DynamicSQLMapper.class);
List<Emp> list = mapper.getEmpByChoose(new Emp(null, "张三", 23, "男", "123@qq.com"));
System.out.println(list);
}
5.foreach
<!-- int deleteMoreByArray(Integer[] eids);-->
<delete id="deleteMoreByArray">
delete from t_emp where
<foreach collection="eids" item="eid" separator="or">
eid = #{eid}
</foreach>
<!--
delete from t_emp where eid in
<foreach collection="eids" item="eid" separator="," open="(" close=")">
#{eid}
</foreach>
-->
</delete>
属性:
collection:设置要循环的数组或集合
item:表示集合或数组中的每一个数据
separator:设置循环体之间的分隔符
open:设置foreach标签中的内容的开始符
close:设置foreach标签中的内容的结束符
测试:
@Test
public void testdeleteMoreByArray() {
SqlSession sqlSession = SqlSessionUtils.getSqlSession();
DynamicSQLMapper mapper = sqlSession.getMapper(DynamicSQLMapper.class);
System.out.println(mapper.deleteMoreByArray(new Integer[]{
5, 6, 7}));
}
6、SQL片段
sql片段,前面介绍trim标签的时候已经运用到了,可以记录一段公共sql片段,在使用的地方通过include标签进行引入
<sql id="empColumns">
eid,ename,age,sex,did
</sql>
select <include refid="empColumns"></include> from t_emp
refid: 连接的sql语句的 id
总结:
/*
* 动态SQL:
* 1.if:根据标签中的test属性对应的表达式决定标签中的内容是否需要拼接到SQL中
* 2.where:
* 当where标签中有内容时,会自动生成where关键字,并且将内容前多余的and和or去掉
* 当where标签中没有内容时,where标签无效果
* 注意:where标签不能将其中内容后面多余的and和or去掉
* 3.trim
* 若标签中有内容时
* prefix|suffix:在trim标签中的内容前面或后面加上指定内容
* prefixOverrides|suffixOverrides:在trim标签中的内容前面或后面去掉指定内容
* 若标签无内容,则标签没有效果
* 4.choose when otherwise 相当于 if...else if...else
* when至少有一个,otherwise至多有一个
* 5.foreach
* collection:设置需要循环的数组或集合
* item:表示数组或集合中的每个数据
* separator:循环体之间的分隔符
* open:foreach标签所循环的所有内容的开始符
* close:foreach标签所循环的所有内容的结束符
* 6.sql标签
* 设置SQL片段:<sql id="empColumns">eid,emp_name,age,sex,email</sql>
* 引用SQL片段:<include refid="empColumns"></include>
*/
二、MyBatis的缓存
1、MyBatis的一级缓存
一级缓存是SqlSession级别的,通过同一个SqlSession查询的数据会被缓存,下次查询相同的数据,就
会从缓存中直接获取,不会从数据库重新访问
使一级缓存失效的四种情况:
- 不同的SqlSession对应不同的一级缓存
- 同一个SqlSession但是查询条件不同
- 同一个SqlSession两次查询期间执行了任何一次增删改操作
- 同一个SqlSession两次查询期间手动清空了缓存
2、MyBatis的二级缓存
二级缓存是SqlSessionFactory级别,通过同一个SqlSessionFactory创建的SqlSession查询的结果会被
缓存;此后若再次执行相同的查询语句,结果就会从缓存中获取
二级缓存开启的条件:
①在核心配置文件中,设置全局配置属性cacheEnabled="true",默认为true,不需要设置
②在映射文件中设置标签<cache/>
③二级缓存必须在SqlSession关闭或提交之后有效
查询的数据所转换的实体类类型必须实现序列化的接口
使二级缓存失效的情况:
两次查询之间执行了任意的增删改,会使一级和二级缓存同时失效
3、二级缓存的相关配置
在mapper配置文件中添加的cache标签可以设置一些属性:
- eviction属性:缓存回收策略
LRU(Least Recently Used) – 最近最少使用的:移除最长时间不被使用的对象。
FIFO(First in First out) – 先进先出:按对象进入缓存的顺序来移除它们。
SOFT – 软引用:移除基于垃圾回收器状态和软引用规则的对象。
WEAK – 弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。
默认的是 LRU。
- flushInterval属性:刷新间隔,单位毫秒
默认情况是不设置,也就是没有刷新间隔,缓存仅仅调用语句时刷新
- size属性:引用数目,正整数
代表缓存最多可以存储多少个对象,太大容易导致内存溢出
- readOnly属性:只读,true/false
true:只读缓存;会给所有调用者返回缓存对象的相同实例。因此这些对象不能被修改。这提供了
很重要的性能优势。
false:读写缓存;会返回缓存对象的拷贝(通过序列化)。这会慢一些,但是安全,因此默认是
false。
4、MyBatis缓存查询的顺序
先查询二级缓存,因为二级缓存中可能会有其他程序已经查出来的数据,可以拿来直接使用。
如果二级缓存没有命中,再查询一级缓存
如果一级缓存也没有命中,则查询数据库
SqlSession关闭之后,一级缓存中的数据会写入二级缓存
Mybatis快速入门介绍到这里就结束啦,感谢你的阅读,一起学习,一起进步!
*点赞,关注,收藏,您的支持是我更新的最大动力!!!*
还没有评论,来说两句吧...