MyBatis——第4章 查询缓存

根据作用域和生命周期分为两种:

一级缓存: 同一线程(SqlSession)间共享缓存,sqlSession一旦关闭,缓存将不复存在。

                   一级缓存只要用就有,一直处于开启状态。 

二级缓存: 不同线程间共享缓存(不同SqlSession 同一个namespace ),与整个应用生命周期是一致的

按照namespace划分,不同的互不干扰

4.1 一级缓存

证明一级缓存是存在的

		Student student = dao.selectStudentById(2);
		System.out.println(student);
		Student student2 = dao.selectStudentById(2);
		System.out.println(student2);

运行结果:只进行了一次查询,证明一级缓存是存在的

Mybatis:证明一级缓存中读取数据的依据是SQL id + SQL语句

Hibernate:缓存中读取数据的依据是查询结果对象id

ORM架构不同,查询依据不同

public interface IStudentDao {

	Student selectStudentById(int id);
	Student selectStudentById2(int id);
}

	public void test02(){
		Student student = dao.selectStudentById(2);
		System.out.println(student);
		Student student2 = dao.selectStudentById(2);
		System.out.println(student2);
	}



	<select id="selectStudentById" resultType="Student">
		select id,name,age,score
		from student 
		where id = #{id}
	</select>
	<select id="selectStudentById2" resultType="Student">
		select id,name,age,score
		from student 
		where id = #{id}
	</select>


查询依据肯定不是对象id

查询依据其实是SQL id和sql语句,缓存底层结构是个map,value是对象id(查询结果),key是SQL id和其对应的sql语句。

增删改操作会刷新一级缓存(清空一级缓存)

无论是否提交

	public void test03(){
		Student student = dao.selectStudentById(2);
		System.out.println(student);
		
		dao.insertStudent(new Student("赵六",25,93));
		
		Student student2 = dao.selectStudentById(2);
		System.out.println(student2);
	}

4.2 内置二级缓存

使用二级缓存的目的不是在多个查询中共享查询结果。而是为了防止同一查询(同SQL id 同SQL语句)的反复执行。

4.2.1 内置二级缓存的开启

 证明二级缓存是存在的

	//证明二级缓存是存在的
	@Test
	public void test01(){
		sqlSession = MyBatisUnils.getSqlSession();
		dao = sqlSession.getMapper(IStudentDao.class);
		Student student = dao.selectStudentById(2);
		System.out.println(student);
		
		sqlSession.close();
		
		sqlSession = MyBatisUnils.getSqlSession();
		dao = sqlSession.getMapper(IStudentDao.class);
		Student student2 = dao.selectStudentById(2);
		System.out.println(student2);
	}

① 对实体进行序列化,

② 在映射文件中添加cache标签  

 cache Hit Ratio 为命中率

增删改对二级缓存的影响

	public void test01(){
		sqlSession = MyBatisUnils.getSqlSession();
		dao = sqlSession.getMapper(IStudentDao.class);
		Student student = dao.selectStudentById(2);
		System.out.println(student);
		
		sqlSession.close();
		
		sqlSession = MyBatisUnils.getSqlSession();
		dao = sqlSession.getMapper(IStudentDao.class);
		dao.insertStudent(new Student("",0,0));
                Student student2 = dao.selectStudentById(2);
		System.out.println(student2);
	}
}

 

1.增删改同样会清空二级缓存

2.二级缓存的清空不是把<key,value>对都干掉,而是将key对应的value置为null,key仍然存在。

3.从DB中进行select查询的条件是:

    ① 缓存中根本就不存在这个key

    ② 缓存中存在key所对应的Entry对象,但是value为null

但不能对一级缓存进行配置

二级缓存的关闭

	<settings>
		<!--全局关闭二级缓存 -->
		<setting name="cacheEnabled" value="false"/>
	</settings>
<!--局部缓存关闭 -->
    <select id="selectStudentById"   useCache="false" resultType="Student">
		select id,name,age,score
		from student 
		where id = #{id}
	</select>

二级缓存的使用原则

① 多个namespace不操作同一张表

② 不要再关联关系表中做增删改操作

      一个接口对应一个对象的处理,一个mapper.xml文件对应一张表的处理

③ 查询多于修改时使用二级缓存

4.2.2 ehcache二级缓存

猜你喜欢

转载自blog.csdn.net/Curry7895/article/details/82808219