Mybatis快速入门(4)

╰半橙微兮° 2023-10-11 18:32 7阅读 0赞

CSDN话题挑战赛第2期
参赛话题:学习笔记

学习之路,长路漫漫,需要您的陪伴。
关注一波,您的关注是我最大的动力。

Mybatis

这篇文章Mybatis快速入门(1)我们介绍了快速掌握Mybatis进行简单CRUD
这篇文章Mybatis快速入门(2)我们介绍了传参以及Mybatis的各种查询。
这篇文章Mybatis快速入门(3)我们介绍了使用Mybatis进行多表查询。
本篇文章,我们介绍一下Mybatis的动态Sql技术和Mybatis的缓存机制。

一、 动态SQL

Mybatis框架的动态SQL技术是一种根据特定条件动态拼装SQL语句的功能,它存在的意义是为了解决
拼接SQL语句字符串时的痛点问题,主要是介绍标签代替sql语句,更加的灵活。

先给出总的接口写法:

  1. public interface DynamicSQLMapper {
  2. /*
  3. * 多条件查询
  4. */
  5. List<Emp> getEmpByCondition(Emp emp);
  6. /*
  7. * 测试choose when otherwise
  8. */
  9. List<Emp> getEmpByChoose(Emp emp);
  10. /*
  11. * 通过数组实现批量删除
  12. */
  13. int deleteMoreByArray(@Param("eids") Integer[] eids);
  14. }

1. if

if标签可通过test属性的表达式进行判断,若表达式的结果为true,则标签中的内容会执行;反之标签中的内容不会执行

  1. <select id="getEmpByCondition" resultType="Emp">
  2. select * from t_emp where 1=1 (没有1=1的话where和and直接连接会报错)
  3. <if test="empName!=null and empName!=''">
  4. and emp_name = #{empName}
  5. </if>
  6. <if test="age!=null and age!=''">
  7. and age = #{age}
  8. </if>
  9. <if test="sex!=null and sex!=''">
  10. and sex = #{sex}
  11. </if>
  12. <if test="email!=null and email!=''">
  13. and email = #{email}
  14. </if>
  15. </select>

2. where

  1. <select id="getEmpByCondition" resultType="Emp">
  2. select * from t_emp
  3. <where>
  4. <if test="empName!=null and empName!=''">
  5. and emp_name = #{empName}
  6. </if>
  7. <if test="age!=null and age!=''">
  8. and age = #{age}
  9. </if>
  10. <if test="sex!=null and sex!=''">
  11. and sex = #{sex}
  12. </if>
  13. <if test="email!=null and email!=''">
  14. and email = #{email}
  15. </if>
  16. </where>
  17. </select>

where和if一般结合使用:

a>若where标签中的if条件都不满足,则where标签没有任何功能,即不会添加where关键字

b>若where标签中的if条件满足,则where标签会自动添加where关键字,并将条件最前方多余的

and去掉

注意:where标签不能去掉条件最后多余的and

3. trim

  1. <select id="getEmpByCondition" resultType="Emp">
  2. select <include refid="empColumns"></include> from t_emp
  3. <trim prefix="where" suffixOverrides="and|or">
  4. <if test="empName!=null and empName!=''">
  5. emp_name = #{empName} and
  6. </if>
  7. <if test="age!=null and age!=''">
  8. age = #{age} and
  9. </if>
  10. <if test="sex!=null and sex!=''">
  11. sex = #{sex} or
  12. </if>
  13. <if test="email!=null and email!=''">
  14. email = #{email} and
  15. </if>
  16. </trim>
  17. </select>

trim用于去掉或添加标签中的内容

常用属性:

prefix:在trim标签中的内容的前面添加某些内容

prefixOverrides:在trim标签中的内容的前面去掉某些内容

suffix:在trim标签中的内容的后面添加某些内容

suffixOverrides:在trim标签中的内容的后面去掉某些内容

前三种sql标签可以用以下例子测试:

  1. @Test
  2. public void testgetEmpByCondition() {
  3. SqlSession sqlSession = SqlSessionUtils.getSqlSession();
  4. DynamicSQLMapper mapper = sqlSession.getMapper(DynamicSQLMapper.class);
  5. List<Emp> list = mapper.getEmpByCondition(new Emp(null, "李四", 21, "男", "123@qq.com"));
  6. System.out.println(list);
  7. }

4.choose.when.otherwise

choose、when、otherwise相当于if…else if…else

  1. <!--List<Emp> getEmpByChoose(Emp emp);-->
  2. <select id="getEmpByChoose" resultType="Emp">
  3. select * from t_emp
  4. <where>
  5. <choose>
  6. <!--when相当于if,一个成立其他的标签就都不执行了,otherwise相当于最后一个else-->
  7. <when test="empName!=null and empName!=''">
  8. emp_name = #{empName};
  9. </when>
  10. <when test="age!=null and age!=''">
  11. age = #{age};
  12. </when>
  13. <when test="sex!=null and sex!=''">
  14. sex = #{sex};
  15. </when>
  16. <when test="email!=null and email!=''">
  17. email = #{email};
  18. </when>
  19. <otherwise>
  20. did = 1;
  21. </otherwise>
  22. </choose>
  23. </where>
  24. </select>

测试:

  1. @Test
  2. public void testGetEmpByChoose() {
  3. SqlSession sqlSession = SqlSessionUtils.getSqlSession();
  4. DynamicSQLMapper mapper = sqlSession.getMapper(DynamicSQLMapper.class);
  5. List<Emp> list = mapper.getEmpByChoose(new Emp(null, "张三", 23, "男", "123@qq.com"));
  6. System.out.println(list);
  7. }

5.foreach

  1. <!-- int deleteMoreByArray(Integer[] eids);-->
  2. <delete id="deleteMoreByArray">
  3. delete from t_emp where
  4. <foreach collection="eids" item="eid" separator="or">
  5. eid = #{eid}
  6. </foreach>
  7. <!--
  8. delete from t_emp where eid in
  9. <foreach collection="eids" item="eid" separator="," open="(" close=")">
  10. #{eid}
  11. </foreach>
  12. -->
  13. </delete>

属性:

collection:设置要循环的数组或集合

item:表示集合或数组中的每一个数据

separator:设置循环体之间的分隔符

open:设置foreach标签中的内容的开始符

close:设置foreach标签中的内容的结束符

测试:

  1. @Test
  2. public void testdeleteMoreByArray() {
  3. SqlSession sqlSession = SqlSessionUtils.getSqlSession();
  4. DynamicSQLMapper mapper = sqlSession.getMapper(DynamicSQLMapper.class);
  5. System.out.println(mapper.deleteMoreByArray(new Integer[]{
  6. 5, 6, 7}));
  7. }

6、SQL片段

sql片段,前面介绍trim标签的时候已经运用到了,可以记录一段公共sql片段,在使用的地方通过include标签进行引入

  1. <sql id="empColumns">
  2. eid,ename,age,sex,did
  3. </sql>
  4. select <include refid="empColumns"></include> from t_emp

refid: 连接的sql语句的 id

总结:

  1. /*
  2. * 动态SQL:
  3. * 1.if:根据标签中的test属性对应的表达式决定标签中的内容是否需要拼接到SQL中
  4. * 2.where:
  5. * 当where标签中有内容时,会自动生成where关键字,并且将内容前多余的and和or去掉
  6. * 当where标签中没有内容时,where标签无效果
  7. * 注意:where标签不能将其中内容后面多余的and和or去掉
  8. * 3.trim
  9. * 若标签中有内容时
  10. * prefix|suffix:在trim标签中的内容前面或后面加上指定内容
  11. * prefixOverrides|suffixOverrides:在trim标签中的内容前面或后面去掉指定内容
  12. * 若标签无内容,则标签没有效果
  13. * 4.choose when otherwise 相当于 if...else if...else
  14. * when至少有一个,otherwise至多有一个
  15. * 5.foreach
  16. * collection:设置需要循环的数组或集合
  17. * item:表示数组或集合中的每个数据
  18. * separator:循环体之间的分隔符
  19. * open:foreach标签所循环的所有内容的开始符
  20. * close:foreach标签所循环的所有内容的结束符
  21. * 6.sql标签
  22. * 设置SQL片段:<sql id="empColumns">eid,emp_name,age,sex,email</sql>
  23. * 引用SQL片段:<include refid="empColumns"></include>
  24. */

二、MyBatis的缓存

1、MyBatis的一级缓存

一级缓存是SqlSession级别的,通过同一个SqlSession查询的数据会被缓存,下次查询相同的数据,就

会从缓存中直接获取,不会从数据库重新访问

使一级缓存失效的四种情况:

  1. 不同的SqlSession对应不同的一级缓存
  2. 同一个SqlSession但是查询条件不同
  3. 同一个SqlSession两次查询期间执行了任何一次增删改操作
  4. 同一个SqlSession两次查询期间手动清空了缓存

2、MyBatis的二级缓存

二级缓存是SqlSessionFactory级别,通过同一个SqlSessionFactory创建的SqlSession查询的结果会被

缓存;此后若再次执行相同的查询语句,结果就会从缓存中获取

二级缓存开启的条件:

  1. ①在核心配置文件中,设置全局配置属性cacheEnabled="true",默认为true,不需要设置
  2. ②在映射文件中设置标签<cache/>
  3. ③二级缓存必须在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快速入门介绍到这里就结束啦,感谢你的阅读,一起学习,一起进步!

*点赞,关注,收藏,您的支持是我更新的最大动力!!!*

发表评论

表情:
评论列表 (有 0 条评论,7人围观)

还没有评论,来说两句吧...

相关阅读

    相关 mybatis快速入门

    Mybatis简介   MyBatis是支持普通SQL查询,存储过程和高级映射的优秀持久层框架。MyBatis消除了几乎所有的JDBC代码和参数的手工设置以及对结果集的检