zoukankan      html  css  js  c++  java
  • MyBatis-缓存机制

    MyBatis-缓存机制         
        MyBatis 包含一个非常强大的查询缓存特性,它可以非常方便地配置和定制。缓存可以极大的提升查询效率。
        MyBatis系统中默认定义了两级缓存。
        一级缓存和二级缓存:
            一级缓存:(本地缓存):SqlSession级别的缓存,一级缓存是一致开启的,没法关闭。方法之间不共用!
                与数据库同一次会话期间查询到的数据放在本地缓存中。
                以后如果需要获取相同的数据,直接从缓存中拿,没必要再去查询数据库;
            二级缓存(全局缓存):
            
            ①默认情况下,只有一级缓存(SqlSession级别的缓存,也称为本地缓存)开启。
            ②二级缓存需要手动开启和配置,他是基于namespace级别的缓存。
            ③为了提高扩展性。MyBatis定义了缓存接口Cache。我们可以通过实现Cache接口来自定义二级缓存。

    1.测试一级缓存【默认是开启的本地缓存的】

     1 public class EmployeeMapperTest {
     2 
     3     
     4     public SqlSessionFactory getSqlSessionFactory() throws IOException{
     5         String resource = "mybatis-config.xml";
     6         InputStream inputStream = Resources.getResourceAsStream(resource);
     7         SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
     8         return sqlSessionFactory;
     9     }
    10     
    11     @Test
    12     public void testFirstLevelCache() throws Exception{
    13         String resource = "mybatis-config.xml";
    14         InputStream inputStream = Resources.getResourceAsStream(resource);
    15         SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    16         
    17         SqlSession sqlSession = sqlSessionFactory.openSession();
    18 
    19         EmployeeMapper mapper = sqlSession.getMapper(EmployeeMapper.class);
    20         Employee emp = mapper.getEmpById(1);
    21         System.out.println(emp);
    22 
    23         EmployeeMapper mapper2 = sqlSession.getMapper(EmployeeMapper.class);
    24         Employee emp2 = mapper2.getEmpById(1);
    25        26     System.out.println(emp==emp2);
    27         sqlSession.close();
    28 
    29     }
    30 }
    因此运行结果为true:
    
    
    DEBUG 12-26 10:18:07,715 ==>  Preparing: select id,last_name,gender,email from tbl_emp where id = ?   (BaseJdbcLogger.java:145) 
    DEBUG 12-26 10:18:07,781 ==> Parameters: 1(Integer)  (BaseJdbcLogger.java:145) 
    DEBUG 12-26 10:18:07,809 <==      Total: 1  (BaseJdbcLogger.java:145) 
    Employee [id=1, lastName=zhangsan, gender=true, email=zhangsan@163.com]
    true
    
    
    emp==emp2比较两个对象,相当于比较他们在堆中的地址值


    一级缓存失效的情况【4种】(没有使用到当前一级缓存的情况,效果就是,还需要再向数据库发出查询)
      1 package com.neuedu.cache;
      2 
      3 import java.io.IOException;
      4 import java.io.InputStream;
      5 
      6 import org.apache.ibatis.io.Resources;
      7 import org.apache.ibatis.session.SqlSession;
      8 import org.apache.ibatis.session.SqlSessionFactory;
      9 import org.apache.ibatis.session.SqlSessionFactoryBuilder;
     10 import org.junit.Test;
     11 
     12 import com.neuedu.entity.Department;
     13 import com.neuedu.entity.Employee;
     14 import com.neuedu.mapper.EmployeeMapper;
     15 
     16 public class testLevelCache {
     17 
     18     public SqlSessionFactory getSqlSessionFactory() throws IOException{
     19         String resource = "mybatis-config.xml";
     20         InputStream inputStream = Resources.getResourceAsStream(resource);
     21         SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
     22         return sqlSessionFactory;
     23     }
     24     
     25     
     26     
     27     //一级缓存    缓存是SqlSession对象独有的,每一个SqlSession对象都有自己的缓存空间
     28         //1.sqlSession不同。
     29         @Test
     30         public void testFirstLevelCache() throws Exception{
     31             String resource = "mybatis-config.xml";
     32             InputStream inputStream = Resources.getResourceAsStream(resource);
     33             SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
     34             
     35             SqlSession sqlSession = sqlSessionFactory.openSession();
     36 
     37             EmployeeMapper mapper = sqlSession.getMapper(EmployeeMapper.class);
     38             Employee emp = mapper.getEmployeeById(1);
     39             System.out.println(emp);
     40             
     41             
     42             sqlSession=sqlSessionFactory.openSession();
     43             EmployeeMapper mapper2 = sqlSession.getMapper(EmployeeMapper.class);
     44             Employee emp2 = mapper2.getEmployeeById(1);
     45             System.out.println(emp==emp2);
     46 
     47             sqlSession.close();
     48 
     49         }
     50         
     51         //2.SqlSession相同,但是查询条件不一样[当前缓存中还没有这个数据]
     52         @Test
     53         public void testFirstLevelCache2() throws IOException{
     54             String resource = "mybatis-config.xml";
     55             InputStream inputStream = Resources.getResourceAsStream(resource);
     56             SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
     57             
     58             SqlSession sqlSession = sqlSessionFactory.openSession();
     59             EmployeeMapper mapper = sqlSession.getMapper(EmployeeMapper.class);
     60             Employee emp = mapper.getEmployeeById(2);
     61             System.out.println(emp);
     62 
     63             Employee emp2 = mapper.getEmployeeById(3);
     64             System.out.println(emp2);    
     65             System.out.println(emp == emp2);
     66             sqlSession.close();
     67         }
     68         
     69         
     70         
     71         
     72         //3.SqlSession相同,但是两次查询之间执行了增删改操作【这次增删改可能对当前数据有影响】
     73         @Test
     74         public void testFirstLevelCache3() throws IOException{
     75             String resource = "mybatis-config.xml";
     76             InputStream inputStream = Resources.getResourceAsStream(resource);
     77             SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
     78             
     79             SqlSession sqlSession = sqlSessionFactory.openSession(true);
     80             EmployeeMapper mapper = sqlSession.getMapper(EmployeeMapper.class);
     81         
     82             Employee emp = mapper.getEmployeeById(2);
     83             System.out.println(emp);
     84             mapper.insertEmployee(new Employee(null, "孙悟空", true, "sunwukong@163.com", new Department(1,"开发部")));
     85             Employee emp2 = mapper.getEmployeeById(2);
     86             System.out.println(emp2);    
     87             System.out.println(emp == emp2);
     88             sqlSession.close();
     89             
     90         }
     91         
     92         
     93         //4.SqlSession相同,手动清除了一级缓存[缓存清空]。     
     94         @Test
     95         public void testGetEmployee() throws IOException{
     96             String resource = "mybatis-config.xml";
     97             InputStream inputStream = Resources.getResourceAsStream(resource);
     98             SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
     99             
    100             SqlSession sqlSession = sqlSessionFactory.openSession(true);
    101             EmployeeMapper mapper = sqlSession.getMapper(EmployeeMapper.class);
    102             Employee emp = mapper.getEmployeeById(2);
    103             System.out.println(emp);
    104             //手动清空缓存
    105             sqlSession.clearCache();
    106             Employee emp2 = mapper.getEmployeeById(2);
    107             System.out.println(emp2);    
    108             System.out.println(emp == emp2);
    109             sqlSession.close();
    110         }
    111 }
    
    

    运行结果:

     1 DEBUG 12-26 10:16:30,839 Cache Hit Ratio [com.neuedu.mapper.EmployeeMapper]: 0.0  (LoggingCache.java:62) 
     2 DEBUG 12-26 10:16:31,271 ==>  Preparing: select * from employee where id=?   (BaseJdbcLogger.java:145) 
     3 DEBUG 12-26 10:16:31,334 ==> Parameters: 1(Integer)  (BaseJdbcLogger.java:145) 
     4 DEBUG 12-26 10:16:31,360 <==      Total: 1  (BaseJdbcLogger.java:145) 
     5 Employee [id=1, username=张三丰, gender=true, email=zhngsanfeng@163.com, dept=null]
     6 DEBUG 12-26 10:16:31,361 Cache Hit Ratio [com.neuedu.mapper.EmployeeMapper]: 0.0  (LoggingCache.java:62) 
     7 DEBUG 12-26 10:16:31,457 ==>  Preparing: select * from employee where id=?   (BaseJdbcLogger.java:145) 
     8 DEBUG 12-26 10:16:31,458 ==> Parameters: 1(Integer)  (BaseJdbcLogger.java:145) 
     9 DEBUG 12-26 10:16:31,461 <==      Total: 1  (BaseJdbcLogger.java:145) 
    10 false

    都是执行两次sql语句

    2.二级缓存:【全局缓存】:基于namespace级别的缓存:一个namespace对应一个二级缓存。
              【一级缓存的范围还是太小了,每次SqlSession一关闭,一级缓存中的数据就消失】
              所以从这个角度讲:能跨sqlSession的缓存为二级缓存!

    mybatis-config.xml:
    <!-- 开启二级缓存 -->
    <setting name="cacheEnabled" value="true"/>

    EmployeeMapper.xml:

    
    
    <!-- 
        二级缓存是namespace级别的,一个namespace【mapper接口】对应一个二级缓存
     -->
    <cache></cache>

    实体类还需要实现Serializable接口:

    public class Employee implements Serializable{

    }

    //二级缓存    
            @Test
            public void testLevelCache() throws Exception{
                String resource = "mybatis-config.xml";
                InputStream inputStream = Resources.getResourceAsStream(resource);
                SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
                
                SqlSession sqlSession = sqlSessionFactory.openSession();
    
                EmployeeMapper mapper = sqlSession.getMapper(EmployeeMapper.class);
                Employee emp = mapper.getEmployeeById(1);
                System.out.println(emp);
                sqlSession.close();
                
                SqlSession sqlSession2 = sqlSessionFactory.openSession();
                EmployeeMapper mapper2 = sqlSession2.getMapper(EmployeeMapper.class);
                Employee emp2 = mapper2.getEmployeeById(1);
                System.out.println(emp==emp2);
    
                sqlSession.close();
    
            }

    运行结果:

    DEBUG 12-26 10:26:31,261 Cache Hit Ratio [com.neuedu.mapper.EmployeeMapper]: 0.0  (LoggingCache.java:62) 
    DEBUG 12-26 10:26:31,731 ==>  Preparing: select * from employee where id=?   (BaseJdbcLogger.java:145) 
    DEBUG 12-26 10:26:31,800 ==> Parameters: 1(Integer)  (BaseJdbcLogger.java:145) 
    DEBUG 12-26 10:26:31,830 <==      Total: 1  (BaseJdbcLogger.java:145) 
    Employee [id=1, username=张三丰, gender=true, email=zhngsanfeng@163.com, dept=null]
    DEBUG 12-26 10:26:31,844 Cache Hit Ratio [com.neuedu.mapper.EmployeeMapper]: 0.5  (LoggingCache.java:62) 
    false

    执行一次sql语句

  • 相关阅读:
    反射(五)之动态代理的作用
    反射(四)之反射在开发中的适用场景及利弊
    反射(三)之通过反射获取构造方法, 成员变量, 成员方法
    反射(二)之反射机制
    反射(一)之初探反射
    java多线程(五)之总结(转)
    java多线程(四)之同步机制
    java多线程(三)之售票案例
    java多线程(二)之实现Runnable接口
    java多线程(一)之继承Thread类
  • 原文地址:https://www.cnblogs.com/double-s/p/8116736.html
Copyright © 2011-2022 走看看