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语句

原文地址:https://www.cnblogs.com/double-s/p/8116736.html