Mybatis 系列全解(3)
- 1. 多对一处理
- 2. 一对多处理
- 3. 动态SQL
- 3.1 什么是动态SQL
- 3.2 搭建环境
- 3.3 IF
- 3.4 Choose(when,otherwise)
- 3.5 Set
- 3.6 SQL片段
- 3.7 Foreach
- 4. 缓存
- 4.1 简介
- 4.2 Mybatis 缓存
- 4.3 一级缓存
- 4.4 二级缓存
- 4.5 缓存原理
1. 多对一处理
1)简介
多个学生对应一个老师
对于学生而言 关联 多个学生关联一个老师
对于老师而言 集合 一个老师有很多学生
先创建两个表 student(id name tid) teacher(id name)
外键:student 的tid和 teacher的id连接
2)测试环境搭建
-
导入lombok
-
新建实体类Teacher Student
-
建立Mapper接口
-
建立Mapper。XML文件
-
在核心配置文件中绑定注册我们的Mapper接口或者文件(方式 )
Student 类
@Data
public class Student {
private int id;
private String name;
private Teacher teacher;
}
3)按照结果嵌套查询(推荐)
4)按照查询嵌套处理
5)回顾Mysql多对一查询方式
-
子查询
-
联表查询
2. 一对多处理
1)简介
比如一个老师有多个学生
环境搭建和以前一样,只是student中的private Teacher teacher;
改为private int tid;
teacher实体类中添加private List<Student> students;
2)按结果嵌套查询:
3)小结
1 关联 - association【多对一】
2 集合 - collection 【一对多】
3 javaType & ofType javaType 用来指定实体类中属性的类型 ofType 用来指定映射到List或者集合中的pojo类型,泛型中的约束类型!
4) 注意点:
-
保证SQL的可读性,尽量保证通俗易懂
-
注意一对多和多对一中,属性名和字段的问题!
-
如果问题不好排查错误,可以使用日志,建议log4j
5) 面试高频
-
Mysql引擎
-
InnoDB底层原理
-
索引
-
索引优化
3. 动态SQL
3.1 什么是动态SQL
什么是动态SQL :根据不同条件生成不同的 SQL 语句。
如果你之前用过 JSTL 或任何基于类 XML 语言的文本处理器,你对动态 SQL 元素可能会感觉似曾相识。在 MyBatis 之前的版本中,需要花时间了解大量的元素。借助功能强大的基于 OGNL 的表达式,MyBatis 3 替换了之前的大部分元素,大大精简了元素种类,现在要学习的元素种类比原来的一半还要少。
- if
- choose (when, otherwise)
- trim (where, set)
- foreach
3.2 搭建环境
a. 创建数据库blog
b. 创建一个基础工程
- 导包
- 编写配置文件
- 编写实体类
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Blog {
private String id;
private String title;
private String author;
private Date createtime;
private int views;
}
- 编写实体类对应Mapper接口和Mapper.xml
3.3 IF
<select id="querybBlogIf" parameterType="map" resultType="blog">
select * from mybatis.blog
<where>
<if test="title != null">
title = #{title}
</if>
<if test="author != null">
and author = #{author}
</if>
</where>
</select>
3.4 Choose(when,otherwise)
<select id="querybBlogChoose" parameterType="map" resultType="blog">
select * from mybatis.blog
<where>
<choose>
<when test="title != null">
title = #{title}
</when>
<when test="author != null">
and author = #{author}
</when>
<otherwise>
and views = #{views}
</otherwise>
</choose>
</where>
</select>
3.5 Set
<update id="updateBlog" parameterType="map">
update mybatis.blog
<set>
<if test="title != null">
title = #{title},
</if>
<if test="author != null">
author = #{author}
</if>
where id = #{id}
</set>
</update>
所谓的动态SQL,本质还是SQL语句,只是我们可以在SQL层面,去执行一个逻辑代码。
3.6 SQL片段
有的时候,我们可能会将一些功能的部分抽取出来,方便复用!
1)使用SQL标签抽取公共的部分(id自定义)
<sql id="title-id">
<if test="title != null">
and title = #{title}
</if>
<if test="author != null">
and author = #{author}
</if>
</sql>
2)在需要使用的地方使用include标签引用即可
<select id="querybBlog" parameterType="map" resultType="blog">
select * from mybatis.blog where 1=1
<include refid="title-id"></include>
</select>
注意:
最好基于单表来定义SQL片段。
不要存在where标签。
3.7 Foreach
where 1 = 1 and (id = 1 or id =2 or id =3)
<select id="queryBlogFor" parameterType="map" resultType="blog">
select * from mybatis.blog
<where>
<foreach collection="ids" item="id" open="and (" separator="or" close=")">
id = #{id}
</foreach>
</where>
</select>
动态SQL就是在拼接SQL语句,我们只要保证SQL的正确性,按照SQL的格式去排列组合就可以了。
建议:先在Mysql写出完整的SQL再对应的去修改称为我们的动态SQL
4. 缓存
4.1 简介
1)什么是缓存Cache ?
-
存在内存中的临时数据。
-
将用户经常查询的数据放在缓存(内存)中,用户去查询数据就不用从磁盘上(关系型数据库数据文件)查询,从缓存中查询,从而提高查询效率,解决了高并发系统的性能问题。
2)为什么使用缓存?
- 减少和数据库的交互次数,减少系统开销,提高系统效率。
3)什么样的数据能使用缓存?
- 经常查询并且不经常改变的数据。
4.2 Mybatis 缓存
1)MyBatis包含一个非常强大的查询缓存特性,它可以非常方便地定制和配置缓存。缓存可以极大的提升查询效率。
2)MyBatis系统中默认定义了两级缓存:一级缓存和二级缓存
-
默认情况下,只有一级缓存开启。(SqlSession级别的缓存,也称为本地缓存)。
-
二级缓存需要手动开启和配置,他是基于namespace级别的缓存。
-
为了提高扩展性,MyBatis定义了缓存接口Cache。我们可以通过实现Cache接口来自定义二级缓存。
4.3 一级缓存
-
—级缓存也叫本地缓存:SqlSession
-
与数据库同一次会话期间查询到的数据会放在本地缓存中。
-
以后如果需要获取相同的数据,直接从缓存中拿,没必须再去查询数据库;
1)测试步骤:
-
开启日志!
-
测试在一个Session中查询两次相同记录
-
查看日志输出
2)缓存失效的情况:
1 查询不同的东西
2 增删改操作,可能会改变原来的数据,所以必定会刷新缓存
3 查询不同的Mapper.xml
4 手动清理缓存
小结:
-
一级缓存默认是开启的,只在一次Sqlsession中有效,也就是拿到连接到关闭连接这个区间段!
-
一级缓存就是一个Map
4.4 二级缓存
1)二级缓存也叫全局缓存,一级缓存作用域太低了,所以诞生了二级缓存;
2)基于namespace级别的缓存,一个名称空间,对应一个二级缓存;
3)工作机制
a. 一个会话查询一条数据,这个数据就会被放在当前会话的一级缓存中;
b. 如果当前会话关闭了,这个会话对应的一级缓存就没了;但是我们想要的是,会话关闭了,一级缓存中的数据被保存到二级缓存中;
c. 新的会话查询信息,就可以从二级缓存中获取内容;
d. 不同的mapper查出的数据会放在自己对应的缓存(map)中;
4)步骤:
a. 开启全局缓存
<setting name="cacheEnabled" value="true"/>
b. 在要使用二级缓存的Mapper中开启
<mapper namespace="com.kuang.dao.UserMapper">
<cache/>
c. 也可以自定义参数
5)测试
问题:我们需要将实体类 序列化!否则会报错!
@Data
public class User implements Serializable {
private int id;
private String name;
private String pwd;
}
小结:
-
只要开启了二级缓存,在同一个Mapper下就有效
-
所有的数据都会先放在一级缓存中
-
只有当会话提交,或者关闭的时候,才会提交到二级缓冲中
4.5 缓存原理
数据库