java后端05 应用技术程序员

MyBatis(4)一级缓存,二级缓存

2017-03-05  本文已影响109人  RonaldoWang

MyBatis的缓存,包括一级缓存,二级缓存。

什么是一级缓存?

一级缓存指的就是sqlsession,在sqlsession中有一个数据区域,是map结构,这个区域就是一级缓存区域。一级缓存中的key是由sql语句、条件、statement等信息组成一个唯一值。一级缓存中的value,就是查询出的结果对象。

什么是二级缓存?

二级缓存指的就是同一个namespace下的mapper,二级缓存中,也有一个map结构,这个区域就是一级缓存区域。一级缓存中的key是由sql语句、条件、statement等信息组成一个唯一值。一级缓存中的value,就是查询出的结果对象。

一级缓存是默认使用的。

二级缓存需要手动开启。

MyBatis缓存框架图

MyBatis缓存框架图

一级缓存原理图

代码测试:

 /**
 * 测试一级缓存
 * @throws Exception
 */
@Test
public void testSelectStudentById() throws Exception {
    SqlSession session1 = sqlSessionFactory.openSession();
    // 拿到代理对象
    StudentMapper mapper = session1.getMapper(StudentMapper.class);
    //第一次查询id为1的Student的信息
    Student student1 = mapper.selectStudentById(1);
    System.out.println(student1);
    //第二次查询时,发现缓存中有id为1的Student的信息,于是从缓存中读取
    Student student2 = mapper.selectStudentById(1);
    System.out.println(student2);
    session1.close();
}

然后debug看一下

再回头看一下上面一级缓存原理图中间那一部分,当修改删除更新时commit,会自动清空缓存

代码测试:

 /**
 * 测试一级缓存
 * @throws Exception
 */
@Test
public void testSelectStudentById() throws Exception {
    SqlSession session1 = sqlSessionFactory.openSession();
    // 拿到代理对象
    StudentMapper mapper = session1.getMapper(StudentMapper.class);
    //第一次查询id为1的Student的信息
    Student student1 = mapper.selectStudentById(1);
    System.out.println(student1);
    //更新操作
    student1.setName("RonaldoWang");
    mapper.updateStudent(student1);
    //commit()就会清空缓存
    session1.commit();
    //第二次查询时,发现缓存中有id为1的Student的信息,于是从缓存中
    Student student2 = mapper.selectStudentById(1);
    System.out.println(student2);
    session1.close();
}

测试结果:


二级缓存原理图

看起来二级缓存与一级缓存相似,只是二级缓存的范围更广,区域划分是namespace,而一级缓存是在sqlsession里面。

1.开启二级缓存

第一步:总开关开启,需要在sqlMapConfig.xml中通过settings标签开启,默认它就是开启的,但还是写上去比较好,容易阅读吧。

第二步:在Mapper.xml下namespace中开启自己的开关

第三步:在PO类中实现序列化操作。

)

之所以需要实现序列化接口,是因为方便反序列化,二级缓存的区域不一定只是在内存中,也有可能在硬盘中。

测试代码:

/**
 * 测试二级缓存
 * @throws Exception
 */
@Test
public void testSelectStudentById() throws Exception {
    SqlSession session1 = sqlSessionFactory.openSession();
    SqlSession session2 = sqlSessionFactory.openSession();
    SqlSession session3 = sqlSessionFactory.openSession();

    StudentMapper mapper1 = session1.getMapper(StudentMapper.class);
    StudentMapper mapper2 = session2.getMapper(StudentMapper.class);
    StudentMapper mapper3 = session2.getMapper(StudentMapper.class);
    
    Student student1 = mapper1.selectStudentById(1);
    System.out.println(student1);
    //这里close很关键,在二级缓存中,close()会将数据放到二级缓存中
    session1.close();
    Student student3 = mapper3.selectStudentById(1);
    System.out.println(student3);
    session3.close();
}

测试结果:


上面代码中session2,和mapper2还没有用到,这里可以用mapper2给数据更新一下,看看是否会将缓存清空?

测试代码

/**
 * 测试二级缓存
 * @throws Exception
 */
@Test
public void testSelectStudentById() throws Exception {
    SqlSession session1 = sqlSessionFactory.openSession();
    SqlSession session2 = sqlSessionFactory.openSession();
    SqlSession session3 = sqlSessionFactory.openSession();

    StudentMapper mapper1 = session1.getMapper(StudentMapper.class);
    StudentMapper mapper2 = session2.getMapper(StudentMapper.class);
    StudentMapper mapper3 = session3.getMapper(StudentMapper.class);
    
    Student student1 = mapper1.selectStudentById(1);
    System.out.println(student1);
    //这里close很关键,在二级缓存中,close()会将数据放到二级缓存中
    session1.close();
    
    
    Student student2 = mapper2.selectStudentById(1);
    student2.setName("小六子");
    mapper2.updateStudent(student2);
    session2.commit();
    session2.close();
    
    
    Student student3 = mapper3.selectStudentById(1);
    System.out.println(student3);
    session3.close();
}

测试结果:


圈出来的看看就能理解了。

禁用缓存

)

刷新缓存

刷新缓存在select语句中默认是false

上一篇下一篇

猜你喜欢

热点阅读