MyBatis(六)缓存机制之一级缓存

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

MyBatis(六)缓存机制之⼀级缓存
⼀、⼀级缓存介绍
1、⼀级缓存(local cache),即本地缓存,作⽤域默认为SqlSession。

当 Session flush 或 close 后,该 session 中的所有 Cache 将被清空。

2、本地缓存不能被关闭,但可以调⽤ clearCache() 来清空本地缓存,或者改变缓存的作⽤域。

3、在 MyBatis3.1 之后,可以配置本地缓存的作⽤域,在 MyBatis.xml 中配置。

4、⼀级缓存是 sqlsession 级别的缓存。

⼀级缓存是⼀直开启的,sqlsession级别的⼀个 map,与数据库同⼀次会话期间查询到的数据会放在本地缓存中。

多个⼀级缓存中的数据不能共⽤。

以后如果需要获取相同的数据,直接从缓存中获取,不必再去查询数据库。

5、⼀级缓存的⼯作机制
同⼀次会话期间只要查询过的数据都会保存在当前的 SqlSession 的⼀个 Map 中
key:hashCode+查询的 SqlId + 编写的 sql 查询语句 + 参数
⼆、⼀级缓存失效的四种情况
⼀级缓存失效情况(没有使⽤到当前⼀级缓存的情况,效果就是,还需要再向数据发送SQL)
1、sqlSession 不同:使⽤不同的 sqlSession 数据库会话,不同的 SqlSession 对应不同的⼀级缓存;
2、sqlSession 相同:但查询条件不同(当前⼀级缓存中还没有这个数据)
3、如果sqlSession相同:两次查询之间执⾏了增删改操作(这次增删改可能对当前数据有影响)
4、如果sqlSession相同,⼿动清除了⼀级缓存(把缓存内容清空)
SqlSession 级别的缓存就相当于⼀个 Map。

三、⼀级缓存演⽰
1、在同⼀个 SqlSession 中查询同⼀条记录
代码:
/**
* mybatis中的⼀级缓存默认开启,是SqlSession级别的
* 即同⼀个SqlSession对于⼀个sql语句,执⾏之后就会存储在缓存中,
* 下次执⾏相同的sql,直接从缓存中取
*/
@Test
public void testFirstLevelCache() throws IOException {
SqlSessionFactory sqlSessionFactory = getsqlSessionFactory();
SqlSession sqlSession = sqlSessionFactory.openSession();
try {
EmployeeMapperCache mapper = sqlSession.getMapper(EmployeeMapperCache.class);
Employee emp01 = mapper.getEmpById(1);
System.out.println("emp01 = " + emp01);
//处理业务
Employee emp02 = mapper.getEmpById(1);
System.out.println("emp02 = " + emp02);
System.out.println(emp01 == emp02);
} finally {
sqlSession.close();
}
}
运⾏结果:
可以看出,查询的是同⼀条记录,但第⼀次是从数据库中查询的,有 SQL 语句,第⼆次查询是就是从缓存(SqlSession)中获取的。

2、从不同的 SqlSession 中查询同⼀条记录
代码:
/**
* 失效情况1:从不同的 SqlSession 中查询同⼀条记录
* @throws IOException
*/
@Test
public void testFirstLevelCacheInvalid1() throws IOException {
SqlSessionFactory sqlSessionFactory = getsqlSessionFactory();
SqlSession sqlSession = sqlSessionFactory.openSession();
try {
EmployeeMapperCache mapper = sqlSession.getMapper(EmployeeMapperCache.class);
Employee emp01 = mapper.getEmpById(1);
System.out.println("emp01 = " + emp01);
//处理业务
SqlSession sqlSession2 = sqlSessionFactory.openSession();
EmployeeMapperCache mapper2 = sqlSession2.getMapper(EmployeeMapperCache.class);
Employee emp02 = mapper2.getEmpById(1);
System.out.println("emp02 = " + emp02);
System.out.println(emp01 == emp02);
} finally {
sqlSession.close();
}
}
运⾏结果:
虽然查询的是同⼀条记录,但是从不同的 SqlSession 中获取的,都从数据库进⾏查询,并没有从缓存中获取。

3、sqlSession 相同,但查询条件不同
代码:
/**
* 失效情况2:sqlSession 相同:但查询条件不同
* @throws IOException
*/
@Test
public void testFirstLevelCacheInvalid2() throws IOException {
SqlSessionFactory sqlSessionFactory = getsqlSessionFactory();
SqlSession sqlSession = sqlSessionFactory.openSession();
try {
EmployeeMapperCache mapper = sqlSession.getMapper(EmployeeMapperCache.class);
Employee emp01 = mapper.getEmpById(1);
System.out.println("emp01 = " + emp01);
//处理业务
Employee emp02 = mapper.getEmpById(3);
System.out.println("emp02 = " + emp02);
System.out.println(emp01 == emp02);
} finally {
sqlSession.close();
}
}
运⾏结果:
使⽤的是同⼀个 sqlSession 对象,但是查询条件不同,也没有⽤到缓存,因为缓存中就没有符合此查询条件的数据。

4、在通过⼀个 SqlSession 中,两次查询之间有增删改操作
代码:
/**
* 失效情况3:在通过⼀个 SqlSession 中,两次查询之间有增删改操作
* @throws IOException
*/
@Test
public void testFirstLevelCacheInvalid3() throws IOException {
SqlSessionFactory sqlSessionFactory = getsqlSessionFactory();
SqlSession sqlSession = sqlSessionFactory.openSession();
try {
EmployeeMapperCache mapper = sqlSession.getMapper(EmployeeMapperCache.class);
Employee emp01 = mapper.getEmpById(1);
System.out.println("emp01 = " + emp01);
//处理业务
mapper.updateEmp(new Employee(3, "John", "1", "John@"));
System.out.println("更新成功");
Employee emp02 = mapper.getEmpById(1);
System.out.println("emp02 = " + emp02);
System.out.println(emp01 == emp02);
} finally {
sqlSession.close();
}
}
运⾏结果:
还是从同⼀个 SqlSession 中查询同⼀条记录,但由于期间涉及了增删改操作,⼀级缓存就会失效。

(因为有可能修改的就是查询的记录,这时再返回,就与数据库中记录不⼀致)
5、在同⼀个 SqlSession 中,⼿动清空缓存
代码:
/**
* 失效情况4:在同⼀个 SqlSession 中,⼿动清空缓存
* @throws IOException
*/
@Test
public void testFirstLevelCacheInvalid4() throws IOException {
SqlSessionFactory sqlSessionFactory = getsqlSessionFactory();
SqlSession sqlSession = sqlSessionFactory.openSession();
try {
EmployeeMapperCache mapper = sqlSession.getMapper(EmployeeMapperCache.class);
Employee emp01 = mapper.getEmpById(1);
System.out.println("emp01 = " + emp01);
//处理业务
sqlSession.clearCache();
Employee emp02 = mapper.getEmpById(1);
System.out.println("emp02 = " + emp02);
System.out.println(emp01 == emp02);
} finally {
sqlSession.close();
}
}
运⾏结果:
虽然是在同⼀个 SqlSession 中进⾏查询的同⼀条记录,但由于在两次查询期间清空了缓存,还需要重新从数据库查询。

相关文档
最新文档