为什么使用缓存?
首次访问时,查询数据库,并将数据存储到内存中;再次访问时直接访问缓存,减少IO、硬盘读写次数、提高效率
Mybatis中的一级缓存和二级缓存?
一级缓存:
它指的是mybatis中的SqlSession对象的缓存。当我们执行完查询之后,查询的结果会同时存在在SqlSession为我们提供的一块区域中。当我们再次查询同样的数据,mybatis会先去SqlSession中查询是否有,有的话直接拿出来使用。当SqlSession对象消失时,Mybatis的一级缓存也就消失了。
二级缓存:
它指的是Mybatis中SqlSessionFactory对象的缓存,由同一个SqlSessioFactory对象创建的SqlSession共享其缓存。
1、mapper
①在UserMapper接口中:
User getUserById(Integer i);
void delectUserById(Integer i);
②UserMapper.xml中
delete from user where id=#{id}
③测试类中:
首先是第二次调用不需要执行Sql语句,只需要在缓存中读取。
一级缓存在同一个sqlSession
@Test
public void testGoCache() throws IOException {
SqlSession sqlSession = sessionFactory.openSession();
UserMapper userMapper1 = sqlSession.getMapper(UserMapper.class);
UserMapper userMapper2 = sqlSession.getMapper(UserMapper.class);
System.out.println("=======第一次查询=========");
User user1 = userMapper1.getUserById(41);
System.out.println(user1);
System.out.println("=======第二次查询========");
User user2 = userMapper2.getUserById(41);
System.out.println(user2);
}
然后是第二次执行需要重新执行sql
同一个sessionFactory创建的不同sqlSession的对象,因为不属于同一个sqlSession,而一级缓存存放在sqlSession的HashMapper,所以需要重新执行sql。
@Test
public void testNoGoCache() throws IOException {
SqlSession sqlSession = sessionFactory.openSession();
SqlSession sqlSession2 = sessionFactory.openSession();
UserMapper userMapper1 = sqlSession.getMapper(UserMapper.class);
UserMapper userMapper2 = sqlSession2.getMapper(UserMapper.class);
System.out.println("=======第一次查询=========");
User user1 = userMapper1.getUserById(41);
System.out.println(user1);
System.out.println("=======第二次查询========");
User user2 = userMapper2.getUserById(41);
System.out.println(user2);
}
最后是在两次相同查询中间执行增删改操作,会导致数据污染(一定要commit()或者close()!!!!!),mybatis会自动清理缓存,而达成第二次执行时执行Sql的操作。
@Test
public void testNoGoCache2() throws IOException {
SqlSession sqlSession = sessionFactory.openSession();
UserMapper userMapper1 = sqlSession.getMapper(UserMapper.class);
UserMapper userMapper2 = sqlSession.getMapper(UserMapper.class);
System.out.println("=======第一次查询=========");
User user1 = userMapper1.getUserById(41);//执行查询
System.out.println(user1);
System.out.println("执行增删改操作");
userMapper1.delectUserById(1);
sqlSession.commit();
System.out.println("=======第二次查询========");
User user2 = userMapper2.getUserById(41);
System.out.println(user2); //执行查询
}
注意:当我们在使用二级缓存时,所缓存的类一定要实现java.io.Serializable接口,这种就可以使用序列化方式来保存对象。
在UserMapper.xml文件中
首先测试二级缓存,第二次执行时直接读取缓存内容
二级缓存是存在sessionFactory中,只要拥有相同的sessionFactory就公用同一个二级缓存
Test
public void testGoCache() throws IOException {
SqlSession sqlSession1 = sessionFactory.openSession();
SqlSession sqlSession2 = sessionFactory.openSession();
UserMapper userMapper = sqlSession1.getMapper(UserMapper.class);
UserMapper userMapper1 = sqlSession2.getMapper(UserMapper.class);
System.out.println("第一次查询");
User user = userMapper.getUserById(41);
System.out.println(user);
sqlSession1.commit(); //第一次查询session执行commit或close,才会把数据写到二级缓存
System.out.println("第二次查询");
User user2 = userMapper1.getUserById(41);
System.out.println(user2);
}
然后是第二次执行时需要执行Sql语句
在不同的sessionFactory中执行相同的方法时,也会重新执行Sql语句
@Test
public void testNoGoCache() throws IOException {
String resource = "mybatis-config.xml";
InputStream inputStream1=Resources.getResourceAsStream(resource);
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream1);
InputStream inputStream2=Resources.getResourceAsStream(resource);
SqlSessionFactory sessionFactory2 = new SqlSessionFactoryBuilder().build(inputStream2);
SqlSession sqlSession = sessionFactory.openSession();
SqlSession sqlSession1 = sessionFactory2.openSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
UserMapper userMapper1 = sqlSession1.getMapper(UserMapper.class);
System.out.println("=============第一次查询============");
User user1 = userMapper.getUserById(41);//执行sql
System.out.println(user1);
sqlSession.commit();
System.out.println("=============第二次查询============");
User user2 = userMapper1.getUserById(41);//执行sql?执行sql
System.out.println(user2);
}
最后是同一个sessionFactory中,两次查询中间执行过其他增删改查的操作(也要commit()或者close())时,第二次查新也需要重新执行Sql。
@Test
public void testNoGoCache2() throws IOException {
SqlSession sqlSession1 = sessionFactory.openSession();
SqlSession sqlSession2 = sessionFactory.openSession();
UserMapper userMapper = sqlSession1.getMapper(UserMapper.class);
UserMapper userMapper1 = sqlSession2.getMapper(UserMapper.class);
System.out.println("第一次查询");
User user = userMapper.getUserById(41);
System.out.println(user);
sqlSession1.commit(); //第一次查询session执行commit或close,才会把数据写到二级缓存
System.out.println("=============两次查询之间执行增删改查=============");
userMapper.delectUserById(1);
sqlSession1.commit();
System.out.println("第二次查询");
User user2 = userMapper1.getUserById(41);
System.out.println(user2);
}