十三、查询缓存

1.一级缓存

同一个SqlSession对象

MyBatis默认开启一级缓存,如果用同样的SqlSession对象查询相同的数据

则只会在第一次查询时向数据库发送SQL语句,并将查询的结果放入到SqlSession中

(作为缓存在后续再次查询该同样的对象时,则直接从缓存中查询该对象即可,即省略了数据库的访问)

public static void queryStudentByStuno() throws IOException {
	Reader reader = Resources.getResourceAsReader("conf.xml");
	SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(reader);
	SqlSession session = sessionFactory.openSession();
	studentMapper studentmapper = session.getMapper(studentMapper.class);
	Student student1 = studentmapper.queryStudentByStuno(2);
    // 测试缓存
	session.commit();
	Student student2 = studentmapper.queryStudentByStuno(2);
	System.out.println(student1);
	System.out.println(student2);
	session.close();
}

2.二级缓存

如果是同一个SqlSession对象进行多次相同的查询,则直接进入一级缓存查询
如果不是同一个SqlSession对象进行多次相同的查询(但是均来自同一个namespace)则进入二级缓存查询

(1)开启二级缓存

MyBatis默认情况没有开启二级缓存,需要手工打开

①conf.xml
<settings>
	<!-- 开启日志,并指定使用的具体日志 -->
	<setting name="logImpl" value="LOG4J"/>
	<!-- 开启二级缓存 -->
	<setting name="cacheEnabled" value="true"/>
</settings>
②studentMapper.xml

在具体的mapper.xml中声明开启(studentMapper.xml中)

<!-- 声明此namespace开启二级缓存 -->
<cache/>

(2)对象序列化

根据异常提示:NotSerializableException可知,MyBatis的二级缓存是将对象放入硬盘文件中
序列化:内存->硬盘
反序列化:硬盘->内存

准备缓存的对象,必须实现了序列化接口

(如果开启的缓存Namespace=“org.lanqiao.mapper.StudentMapper”)

可知序列化对象为Student,因此需要将Student序列化(序列化Student类,以及Student的级联属性、和父类)

package nuc.hzb.entity;

import java.io.Serializable;

public class Student implements Serializable {
	
	private static final long serialVersionUID = 1L;
	
	private int stuNo;
	private String stuName;
	private int stuAge;
	private Address address;
	
	public Student() {}

	public int getStuNo() {
		return stuNo;
	}

	public void setStuNo(int stuNo) {
		this.stuNo = stuNo;
	}

	public String getStuName() {
		return stuName;
	}

	public void setStuName(String stuName) {
		this.stuName = stuName;
	}

	public int getStuAge() {
		return stuAge;
	}

	public void setStuAge(int stuAge) {
		this.stuAge = stuAge;
	}

	public Address getAddress() {
		return address;
	}

	public void setAddress(Address address) {
		this.address = address;
	}

	public static long getSerialversionuid() {
		return serialVersionUID;
	}

	@Override
	public String toString() {
		return "Student [stuNo=" + stuNo + ", stuName=" + stuName + ", stuAge=" + stuAge + ", address=" + address + "]";
	}

}

(3)测试

public static void queryAllStudents() throws IOException {
	Reader reader = Resources.getResourceAsReader("conf.xml");
	SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(reader);
	SqlSession session = sessionFactory.openSession();
	studentMapper studentmapper = session.getMapper(studentMapper.class);
	List<Student> students = studentmapper.queryAllStudents();
	System.out.println(students);
    
    // 触发将对象写入二级缓存的时机:SqlSession对象的close()方法,一次性全部反过来
	session.close();
		
	SqlSession session1 = sessionFactory.openSession();
	studentMapper studentmapper1 = session1.getMapper(studentMapper.class);
	List<Student> students1 = studentmapper1.queryAllStudents();
	System.out.println(students1);
	session1.close();
    
    // 测试命中率
    SqlSession session2 = sessionFactory.openSession();
	studentMapper studentmapper2 = session2.getMapper(studentMapper.class);
	List<Student> students2 = studentmapper2.queryAllStudents();
	System.out.println(students2);
	session2.close();	
}
DEBUG [main] - ==>  Preparing: select * from student 
DEBUG [main] - ==> Parameters: 
DEBUG [main] - <==      Total: 3
[Student [stuNo=2, stuName=黄朝博, stuAge=18, address=null], Student [stuNo=4, stuName=hhh, stuAge=20, address=null], Student [stuNo=5, stuName=黄朝博, stuAge=20, address=null]]
DEBUG [main] - Resetting autocommit to true on JDBC Connection [oracle.jdbc.driver.T4CConnection@34e9fd99]
DEBUG [main] - Closing JDBC Connection [oracle.jdbc.driver.T4CConnection@34e9fd99]
DEBUG [main] - Returned connection 887750041 to pool.
DEBUG [main] - Cache Hit Ratio [nuc.hzb.mapper.studentMapper]: 0.5
[Student [stuNo=2, stuName=黄朝博, stuAge=18, address=null], Student [stuNo=4, stuName=hhh, stuAge=20, address=null], Student [stuNo=5, stuName=黄朝博, stuAge=20, address=null]]
DEBUG [main] - Cache Hit Ratio [nuc.hzb.mapper.studentMapper]: 0.6666666666666666
[Student [stuNo=2, stuName=黄朝博, stuAge=18, address=null], Student [stuNo=4, stuName=hhh, stuAge=20, address=null], Student [stuNo=5, stuName=黄朝博, stuAge=20, address=null]]

3.总结

MyBatis自带二级缓存
二级缓存:同一个namespace生成的mapper对象
回顾:namespace的值就是接口的全类名(包名.类名),通过接口可以产生代理对象(studentMapper对象)
namespace决定了studentMapper对象的产生

结论:只要产生的xxxMapper对象来自于同一个namespace,则这些对象共享二级缓存
注意:二级缓存的范围是同一个namespace,如果有多个xxxMapper.xml的namespace值相同,则通过这些xxxMapper.xml产生的xxxMapper对象仍然共享二级缓存

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值