MyBatis缓存

  • 为什么使用缓存?

    首次访问时,查询数据库,并将数据存储到内存中;再次访问时直接访问缓存,减少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接口,这种就可以使用序列化方式来保存对象。

MyBatis缓存_第1张图片

开启二级缓存 

在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);
    }

你可能感兴趣的:(缓存,java,mybatis,sql,开发语言)