目录
一、什么是缓存:
缓存cache:简单来说缓存就是数据交换的缓冲区,当应用程序需要从数据库读取数据时,先从数据库取出,放置在缓冲区,应用程序再从缓冲区读取数据。【jdbc没有缓存,每次查询对象都得new对象,mybatis提供一种缓存机制,先从数据库把数据放在缓存,需要的时候再去读取。节省资源,提高效率,减少对数据库数据的读取次数 】具体如下图所示:
- 编辑
二、缓存的优缺点:
缓存的优点:快速读取
缓存的缺点:数据可能不是最新的。
三、缓存的术语:【针对缓存数据】
- 未命中:需要的数据在缓存中未找到结果,重新获取。
- 命中:需要的数据在缓存中找到结果
四、缓存的适用性:【适合的,反之不适合】
经常查询比并且不经常改变的。
数据的正确与否对最终的结果影响不大的
五、缓存的分类:
一级缓存:会话sqlsession,针对一次会话。
二级缓存:映射器级别的缓存,针对不同namespace的映射器。
自定义缓存
六、细说mybatis的一级缓存和二级缓存
1.一级缓存:
【操作的是sqlsession对象,默认是开启的】
编辑
1.1一级缓存的配置
【在主配置文件中配置。详情如下图】
1.2一级缓存的工作流程【命中】:如下图
1.3一级缓存的工作流程【未命中】:如下图
1.4一级缓存的案例演示:
1.4.1创建传递数据的实体类,代码如下
package com.shang.Bean;
import java.util.Date;
public class Student {
private int sid;
private String sname;
private Date birthday;
private String ssex;
private int classid;
private Banji bj;
public int getSid() {
return sid;
}
public void setSid(int sid) {
this.sid = sid;
}
public String getSname() {
return sname;
}
public void setSname(String sname) {
this.sname = sname;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String getSsex() {
return ssex;
}
public void setSsex(String ssex) {
this.ssex = ssex;
}
public int getClassid() {
return classid;
}
public void setClassid(int classid) {
this.classid = classid;
}
public Banji getBj() {
return bj;
}
public void setBj(Banji bj) {
this.bj = bj;
}
public Student() {
super();
// TODO Auto-generated constructor stub
}
@Override
public String toString() {
return "Student [sid=" + sid + ", sname=" + sname + ", birthday=" + birthday + ", ssex=" + ssex + ", classid="
+ classid + ", bj=" + bj + "]";
}
public Student(int sid, String sname, Date birthday, String ssex, int classid, Banji bj) {
super();
this.sid = sid;
this.sname = sname;
this.birthday = birthday;
this.ssex = ssex;
this.classid = classid;
this.bj = bj;
}
}
1.4.2StudentMapper映射文件代码如下
package com.shang.Mapper;
import java.util.List;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.InsertProvider;
import org.apache.ibatis.annotations.One;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.SelectProvider;
import org.apache.ibatis.annotations.UpdateProvider;
import org.apache.ibatis.jdbc.SQL;
import org.apache.ibatis.mapping.FetchType;
import com.shang.Bean.Student;
@Results({
@Result(column="classid", property="classid"),
@Result( property="bj",column="classid" ,one=@One(select="com.shang.Mapper.BanjiMapper.findStudentbyId",
fetchType =FetchType.LAZY ))
})
@Select("select * from student")
public List<Student> findStudentbyId(in
}
1.4.3测试类代码如下
package com.shang.test;
import java.io.IOException;
import java.sql.Connection;
import java.util.Date;
import java.util.List;
import org.apache.ibatis.session.SqlSession;
import com.shang.Bean.Student;
import com.shang.Mapper.BanjiMapper;
import com.shang.Mapper.studentMapper;
import com.shang.dao.DaoUtil;
public class Mybatiesdemo {
public static void main(String[] args) throws IOException {
//一对一,一学生对应一个班级
SqlSession sqlsession = DaoUtil.getSqlsession();
studentMapper mapper = sqlsession.getMapper(studentMapper.class);
// List<Student> findStudentbyId = mapper.findStudentbyId(1);
// Student student = findStudentbyId.get(0);
// System.out.println(student);
//一级缓存
Student findStudentbyId1 = mapper.findStudentbyId1(5);
System.out.println(findStudentbyId1);
System.out.println("**********");
Student findStudentbyId2 = mapper.findStudentbyId1(5);
System.out.println(findStudentbyId2);
System.out.println(findStudentbyId1.equals(findStudentbyId2));
//这里输出的是true 因为一级缓存原因,第一次查询之后的值会放在一级缓存中所以次拿到的是同一个值。
}
}
1.4.4测试结果如下:
1.5一级缓存失效的情况【重要的四个一级缓存失效】
1.不同的Sqlsession对应的一级缓存【不同的sqlsession】。
//一级缓存失效的四种情况
//第一种
System.out.println("~~~~~~~~~~~~~~~~~~~~~~~");
SqlSession sqlsession2 = DaoUtil.getSqlsession();
studentMapper mapper2 = sqlsession2.getMapper(studentMapper.class);
Student findStudentbyId3= mapper2.findStudentbyId1(5);
System.out.println(findStudentbyId3);
编辑
2.同一个sqlsession条件不一样,缓存失效(SQL语句不同)【失效就会再去执行一次SQL查询】
//第二种
System.out.println("~~~~~~~~~~~~~~~~~~~~~~~");
Student findStudentbyId4 = mapper2.findStudentbyId1(6);
System.out.println(findStudentbyId4);
3.同一个sqlsession两次查询之间执行任何一次增删改操作,缓存就失效了。【失效就会再去执行一次SQL查询】
//第三种
System.out.println("~~~~~~~~~~~~~~~~~~");
Student findStudentbyId51 = mapper2.findStudentbyId1(6);
System.out.println(findStudentbyId51);
int insertStudent = mapper2.insertStudent();
System.out.println(insertStudent);
System.out.println("____________");
Student findStudentbyId5 = mapper2.findStudentbyId1(6);
System.out.println(findStudentbyId5);
4.同一个sqlsession两次查询期间手动清空了缓存,使用sqlsession.clearCache(), 缓存失效。【失效就会再去执行一次SQL查询】
//第四种
System.out.println("~~~~~~~~~~~~~~~~~~~~~");
sqlsession2.clearCache();
Student findStudentbyId6 = mapper2.findStudentbyId1(6);
System.out.println(findStudentbyId6);
2.二级缓存:【不建议用】
2.1开启二级缓存的方式:
2.1.1配置步骤:
1.在mybatis的sqlMapConfig.xml 中配置
2.在mybatis的sqlmap中配置(mapper.xml中配置)
3.在使用的操作
2.1.2注解:
2.2二级缓存的优缺点:
优:相对一级缓存操作的是sqlsessionfactory,实现了缓存数据的共享。可控性更强
缺:极大可能会出现错误数据。【分布式下必然会读到错误的数据】
3.自定义缓存:
实现缓存接口,引入第三方缓存引入【Redis等第三方内存库作为mybatis的缓存】。
七、一级缓存和二级缓存的区别
1.操作对象不一样【一级缓存是sqlsession/二级缓存是sqlsessionFactory】
2.放数据的地方不一样【一级缓存是磁盘,二级缓存是内存】
注意:
- cache和buffer的区别
- cache:输出型的缓存
- buffer:输入型的缓存