MyBatis(下)

1、MayBatis的缓存:

        缓存通过减少IO(读写文件)的方式,来提高程序的执行效率。mybatis的缓存将select语句的查询结果放到缓存(内存)当中,下一次还是这条select语句的话,直接从缓存中取,不再查数据库。一方面是减少了IO,另一方面不再执行繁琐的查找算法,效率大大提升。

mybatis缓存包括:

  • 一级缓存:将查询到的数据存储到SqlSession中。(当前的会话)
  • 二级缓存:将查询到的数据存储到SqlSessionFactory中。(对于整个数据库)
  • 或者集成其它第三方的缓存:比如EhCache【Java语言开发的】、Memcache【C语言开发的】等。

缓存只针对于DQL语句,也就是说缓存机制只对应select语句

(1)一级缓存:

        默认开启,同一个SqlSesion级别共享的缓存,在一个SqlSession的生命周期内,如果执行2次相同的SQL查询,那么第二次SQL查询会直接取缓存的数据,而不是到数据库中查询,当然,若第一次和第二次相同的SQL查询之间,执行了DML(INSERT/UPDATE/DELETE),则一级缓存会被清空,第二次查询相同SQL仍然会到数据库中查找数据。

一级缓存在下面情况会被清除

  1. 在同一个SqlSession下执行增删改操作时(不必提交),会清除一级缓存(DML的操作和表没有关系,即使操作的不是同一个表也会触发这操作!)
  2. SqlSession提交或关闭时(关闭时会自动提交),会清除一级缓存
  3. 对mapper.xml中的某个CRUD标签,设置属性flushCache=true,这样会导致该MappedStatement的一级缓存,二级缓存都失效,在全局配置文件中设置 ,这样会使一级缓存失效,二级缓存不受影响
  4. 执行sqlSession的clearCache(),方法后一级缓存会被清空(手动清空缓存)

MappedStatement是指:一个CRUD标签在mybatis中会被封装成一个MappedStatement。

测试

mapper接口: 

 //通过id查询汽车
    Car selectById(Long id);

mapper映射文件:

    

测试类:  使用的是同一个mapper

 //测试一级缓存
    @Test
    public  void test1(){
        SqlSession sqlSession = SqlSessionUtil.openSession();
        CarMapper mapper = sqlSession.getMapper(CarMapper.class);
        Car car1 = mapper.selectById(194L);
        System.out.println(car1);

        Car car2 = mapper.selectById(194L);
        System.out.println(car2);

        //关闭
        sqlSession.close();

    }

测试结果:

执行相同的sql的时候,第二次没有执行sql语句,而是直接使用缓存! 

换换测试方式:既然是在同一个sqlsession那么和创建的mapper应该没有什么关系吧

 //使用的是不同mapper(狗头保命sqlsession)
    @Test
    public  void test2(){
        SqlSession sqlSession = SqlSessionUtil.openSession();
        CarMapper mapper = sqlSession.getMapper(CarMapper.class);
        Car car1 = mapper.selectById(194L);
        System.out.println(car1);

        Car car2 = mapper.selectById(194L);
        System.out.println(car2);

        //关闭
        sqlSession.close();

    }

 测试结果 还是一个

获取不同的Sqlsession对象测试:

 @Test
    public  void test3() throws IOException {
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder=new SqlSessionFactoryBuilder();
        SqlSessionFactory sessionFactory = sqlSessionFactoryBuilder.build(Resources.getResourceAsReader("mybatis-config.xml"));
        SqlSession sqlSession = sessionFactory.openSession();
        SqlSession sqlSession1 = sessionFactory.openSession();
        CarMapper mapper = sqlSession.getMapper(CarMapper.class);
        Car car = mapper.selectById(194L);
        System.out.println(car);

        CarMapper mapper1 = sqlSession1.getMapper(CarMapper.class);
        Car car1 = mapper1.selectById(194L);
        System.out.println(car1);
        sqlSession.close();
        sqlSession1.close();
    }

 测试结果:MyBatis(下)_第1张图片

        测试的结果是使用的是两个sqlsession对象,所以导致这样的情况发生。由于只会存在同一个SQL Session的缓存,所以此次的查询使用啦两个sql语句。

(2)二级缓存:

        默认关闭,可通过全局配置文件中的开启二级缓存总开关,然后在某个具体的mapper.xml中增加,即开启了该mapper.xml的二级缓存。二级缓存是mapper级别的缓存,粒度比一级缓存大,多个SqlSession可以共享同一个mapper的二级缓存。注意开启二级缓存后,SqlSession需要提交或者关闭,查询的数据才会被刷新到二级缓存当中。

使用二级缓存需要具备以下几个条件:

1、 全局性地开启或关闭所有映射器配置文件中已配置的任何缓存。默认就是true,无需设置。

MyBatis(下)_第2张图片

2、在需要使用二级缓存的SqlMapper.xml文件中添加配置:

3、使用二级缓存的实体类对象必须是可序列化的,也就是必须实现java.io.Serializable接口

MyBatis(下)_第3张图片

4、SqlSession对象关闭或提交之后,一级缓存中的数据才会被写入到二级缓存当中。此时二级缓存才可用。

测试类:

@Test
    public  void test4() throws IOException {
        SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsReader("mybatis-config.xml"));

        SqlSession sqlSession = sessionFactory.openSession();
        CarMapper mapper = sqlSession.getMapper(CarMapper.class);
        Car car = mapper.selectById2(194L);
        System.out.println(car);
        SqlSession sqlSession1 = sessionFactory.openSession();
        CarMapper mapper1 = sqlSession1.getMapper(CarMapper.class);
        Car car1 = mapper1.selectById2(194L);
        System.out.println(car1);

      
    }

         这里避免了一级缓存的情况,使用的不同sqlSession对象,但是没有关闭和提交所以应该是两条的sql语句。

测试结果:

MyBatis(下)_第4张图片

执行的是两个sql语句!

那么将上面的测试的代码稍稍稍修改一下,然后体现二级缓存的功能!

 MyBatis(下)_第5张图片

测试结果:

MyBatis(下)_第6张图片 触发二级缓存!只是执行啦一次的sql语句!

你可能感兴趣的:(Mybatis,mybatis,java,spring)