MyBatis 二级缓存机制[通俗易懂]

MyBatis 二级缓存机制[通俗易懂]MyBatis 二级缓存机制

大家好,又见面了,我是你们的朋友全栈君。

文章转自:http://blog.csdn.net/u010858605/article/details/70906617?locationNum=2&fps=1点击打开链接

MyBatis 提供了查询缓存来缓存数据,以提高查询的性能。MyBatis 的缓存分为一级缓存二级缓存

  • 一级缓存是 SqlSession 级别的缓存
  • 二级缓存是 mapper 级别的缓存,多个 SqlSession 共享

MyBatis 二级缓存机制[通俗易懂]

在实际的项目开发中,通常对数据库的查询性能要求很高,而mybatis提供了查询缓存来缓存数据,从而达到提高查询性能的要求。

mybatis的查询缓存分为一级缓存和二级缓存,一级缓存是SqlSession级别的缓存,二级缓存时mapper级别的缓存,二级缓存是多个SqlSession共享的。mybatis通过缓存机制减轻数据压力,提高数据库性能。

一级缓存:

mybatis的一级缓存是SQLSession级别的缓存,在操作数据库时需要构造SqlSession对象,在对象中有一个HashMap用于存储缓存数据,不同的SqlSession之间缓存数据区域(HashMap)是互相不影响的。

一级缓存的作用域是SqlSession范围的,当在同一个SqlSession中执行两次相同的sql语句时,第一次执行完毕会将数据库中查询的数据写到缓存(内存)中,第二次查询时会从缓存中获取数据,不再去底层进行数据库查询,从而提高了查询效率。需要注意的是:如果SqlSession执行了DML操作(insert、update、delete),并执行commit()操作,mybatis则会清空SqlSession中的一级缓存,这样做的目的是为了保证缓存数据中存储的是最新的信息,避免出现脏读现象。

当一个SqlSession结束后该SqlSession中的一级缓存也就不存在了,Mybatis默认开启一级缓存,不需要进行任何配置。

注意:Mybatis的缓存机制是基于id进行缓存,也就是说Mybatis在使用HashMap缓存数据时,是使用对象的id作为key,而对象作为value保存

例子说明:

工程架构图:

MyBatis 二级缓存机制[通俗易懂]

sql语句:

[sql] 
view plain  
copy

  1. CREATE TABLE employee(  
  2. id INT(11) PRIMARY KEY AUTO_INCREMENT,  
  3. loginname VARCHAR(18),  
  4. PASSWORD VARCHAR(18),  
  5. NAME VARCHAR(18) DEFAULT NULL,  
  6. sex CHAR(2) DEFAULT NULL,  
  7. age INT(11) DEFAULT NULL,  
  8. phone VARCHAR(21),  
  9. sal DOUBLE,  
  10. state VARCHAR(18)  
  11. );  
  12. INSERT INTO employee (loginname,PASSWORD,NAME,sex,age,phone,sal,state) VALUES(‘jack’,‘123456’,‘杰克’,‘男’,26,‘12345678936’,9800,‘ACTIVE’);  
  13. INSERT INTO employee (loginname,PASSWORD,NAME,sex,age,phone,sal,state) VALUES(‘rose’,‘123456’,‘露丝’,‘女’,21,‘78965412395’,6800,‘ACTIVE’);  
  14. INSERT INTO employee (loginname,PASSWORD,NAME,sex,age,phone,sal,state) VALUES(‘tom’,‘123456’,‘汤姆’,‘男’,25,‘13902017777’,8800,‘ACTIVE’);  
  15. INSERT INTO employee (loginname,PASSWORD,NAME,sex,age,phone,sal,state) VALUES(‘alice’,‘123456’,‘爱丽丝’,‘女’,20,‘74185296375’,5800,‘ACTIVE’);  

log4j.properties:

[plain] 
view plain  
copy

  1. log4j.rootLogger=ERROR, stdout  
  2. log4j.logger.com.zxc.mapper.EmployeeMapper=DEBUG  
  3. log4j.appender.console=org.apache.log4j.ConsoleAppender  
  4. log4j.appender.console.layout=org.apache.log4j.PatternLayout  
  5. log4j.appender.console.layout.ConversionPattern=[%-12d{HH\:mm\:ss.SS}] [%p] %l %m%n  
  6.     
  7. log4j.appender.stdout=org.apache.log4j.ConsoleAppender  
  8. log4j.appender.stdout.layout=org.apache.log4j.PatternLayout  
  9. log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] – %m%n  

mybatis-config.xml:

[html] 
view plain  
copy

  1. <?xml version=“1.0” encoding=“UTF-8”?>  
  2. <!DOCTYPE configuration PUBLIC “-//mybatis.org//DTD Config 3.0//EN”   
  3. “http://mybatis.org/dtd/mybatis-3-config.dtd”>  
  4.   
  5. <configuration>     
  6.     <!– mappers 告诉了Mybatis去哪里找持久化类的映射文件 –>  
  7.     <settings>  
  8.         <!– 要使延迟加载生效必须配置下面两个属性 –>  
  9.         <setting name=“lazyLoadingEnabled” value=“true”/>  
  10.         <setting name=“aggressiveLazyLoading” value=“false”/>  
  11.         <setting name=“logImpl” value=“LOG4J” />  
  12.     </settings>  
  13.     <environments default=“mysql”>  
  14.         <environment id=“mysql”>  
  15.             <!– 指定事务管理类型,type=”JDBC”指直接简单使用了JDBC的提交和回滚设置–>  
  16.             <transactionManager type=“JDBC”/>  
  17.             <!– dataSource指数据源配置,POOLED是JDBC连接对象的数据源连接池的实现 –>                 
  18.             <dataSource type=“POOLED”>  
  19.                 <property name=“driver” value=“com.mysql.jdbc.Driver”/>  
  20.                 <property name=“url” value=“jdbc:mysql://127.0.0.1:3306/mybatis”/>  
  21.                 <property name=“username” value=“root”/>  
  22.                 <property name=“password” value=“sfhq1866”/>  
  23.             </dataSource>  
  24.         </environment>  
  25.     </environments>  
  26.       
  27.     <mappers>  
  28.         <mapper resource=“com/zxc/mapper/EmployeeMapper.xml”/>   
  29.     </mappers>  
  30. </configuration>  

Employee.java:

[java] 
view plain  
copy

  1. package com.zxc.domain;  
  2.   
  3. import java.io.Serializable;  
  4.   
  5. public class Employee implements Serializable {  
  6.     /** 
  7.      *  
  8.      */  
  9.     private static final long serialVersionUID = 1L;  
  10.     private Integer id;  
  11.     private String loginname;  
  12.     private String password;  
  13.     private String name;  
  14.     private String sex;  
  15.     private String age;  
  16.     private String phone;  
  17.     private Double sal;  
  18.     private String state;  
  19.     public Integer getId() {  
  20.         return id;  
  21.     }  
  22.     public void setId(Integer id) {  
  23.         this.id = id;  
  24.     }  
  25.     public String getLoginname() {  
  26.         return loginname;  
  27.     }  
  28.     public void setLoginname(String loginname) {  
  29.         this.loginname = loginname;  
  30.     }  
  31.     public String getPassword() {  
  32.         return password;  
  33.     }  
  34.     public void setPassword(String password) {  
  35.         this.password = password;  
  36.     }  
  37.     public String getName() {  
  38.         return name;  
  39.     }  
  40.     public void setName(String name) {  
  41.         this.name = name;  
  42.     }  
  43.     public String getSex() {  
  44.         return sex;  
  45.     }  
  46.     public void setSex(String sex) {  
  47.         this.sex = sex;  
  48.     }  
  49.     public String getAge() {  
  50.         return age;  
  51.     }  
  52.     public void setAge(String age) {  
  53.         this.age = age;  
  54.     }  
  55.     public String getPhone() {  
  56.         return phone;  
  57.     }  
  58.     public void setPhone(String phone) {  
  59.         this.phone = phone;  
  60.     }  
  61.     public Double getSal() {  
  62.         return sal;  
  63.     }  
  64.     public void setSal(Double sal) {  
  65.         this.sal = sal;  
  66.     }  
  67.     public String getState() {  
  68.         return state;  
  69.     }  
  70.     public void setState(String state) {  
  71.         this.state = state;  
  72.     }  
  73. }  

EmployeeMapper.xml:

[html] 
view plain  
copy

  1. <?xml version=“1.0” encoding=“UTF-8”?>  
  2. <!DOCTYPE mapper PUBLIC “-//mybatis.org//DTD Mapper 3.0//EN”   
  3. “http://mybatis.org/dtd/mybatis-3-mapper.dtd”>  
  4. <mapper namespace=“com.zxc.mapper.EmployeeMapper”>  
  5.     <select id=“selectEmployeeById” parameterType=“int” resultType=“com.zxc.domain.Employee”>  
  6.         SELECT * FROM employee WHERE id = #{id}  
  7.     </select>  
  8.     <!– 查询所有Employee –>  
  9.     <select id=“selectAllEmployee” parameterType=“int” resultType=“com.zxc.domain.Employee”>  
  10.         SELECT * FROM employee  
  11.     </select>  
  12.     <!– 根据id删除Employee –>  
  13.     <delete id=“deleteEmployeeById” parameterType=“int”>  
  14.         DELETE FROM employee WHERE id = #{id}  
  15.     </delete>  
  16. </mapper>  

EmployeeMapper.java:

[java] 
view plain  
copy

  1. package com.zxc.mapper;  
  2.   
  3. import java.util.List;  
  4.   
  5. import com.zxc.domain.Employee;  
  6.   
  7. public interface EmployeeMapper {  
  8.     //根据id查询Employee  
  9.     Employee selectEmployeeById(Integer id);  
  10.     //查询所有Employee  
  11.     List<Employee> selectAllEmployee();  
  12.     //根据id删除Employee  
  13.     void deleteEmployeeById(Integer id);  
  14. }  

工厂工具类:ZSqlSessionFactory.java:

[java] 
view plain  
copy

  1. package com.zxc.factory;  
  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.   
  11. public class ZSqlSessionFactory {  
  12.     private static SqlSessionFactory sqlSessionFactory = null;  
  13.     static{  
  14.         try {  
  15.             InputStream inputStream = Resources.getResourceAsStream(“mybatis-config.xml”);  
  16.             sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);            
  17.         } catch (IOException e) {  
  18.             e.printStackTrace();  
  19.         }  
  20.     }  
  21.     //获取SqlSession对象的静态方法  
  22.     public static SqlSession getSqlSession(){  
  23.         return sqlSessionFactory.openSession();  
  24.     }  
  25.     //获取SqlSessionFactory的静态方法  
  26.     public static SqlSessionFactory getSessionFactory(){  
  27.         return sqlSessionFactory;  
  28.     }  
  29. }  

执行方法类一:OneLevelCacheTest.java

[java] 
view plain  
copy

  1. package com.zxc.test;  
  2.   
  3. import org.apache.ibatis.session.SqlSession;  
  4.   
  5. import com.zxc.domain.Employee;  
  6. import com.zxc.factory.ZSqlSessionFactory;  
  7. import com.zxc.mapper.EmployeeMapper;  
  8.   
  9. public class OneLevelCacheTest {  
  10.     public void testCache1(){  
  11.         //使用工厂类获得SqlSession对象  
  12.         SqlSession sqlSession = ZSqlSessionFactory.getSqlSession();  
  13.         //获得EmployeeMapping对象  
  14.         EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);  
  15.         Employee employee1 = employeeMapper.selectEmployeeById(1);  
  16.         System.out.println(employee1);  
  17.         //再次查询id为1的Employee对象,因为是同一个SqlSession,所以会从之前的一级缓存中查找数据  
  18.         Employee employee2 = employeeMapper.selectEmployeeById(1);  
  19.         System.out.println(employee2);  
  20.         sqlSession.close();  
  21.     }  
  22.     public static void main(String[] args) {  
  23.         OneLevelCacheTest t = new OneLevelCacheTest();  
  24.         t.testCache1();  
  25.     }  
  26. }  



运行之后结果:

[plain] 
view plain  
copy

  1. 2017-04-01 18:07:21,577 DEBUG [com.zxc.mapper.EmployeeMapper.selectEmployeeById] – ==>  Preparing: SELECT * FROM employee WHERE id = ?   
  2. 2017-04-01 18:07:21,637 DEBUG [com.zxc.mapper.EmployeeMapper.selectEmployeeById] – ==> Parameters: 1(Integer)  
  3. 2017-04-01 18:07:21,720 DEBUG [com.zxc.mapper.EmployeeMapper.selectEmployeeById] – <==      Total: 1  
  4. com.zxc.domain.Employee@6a33ee9b  
  5. com.zxc.domain.Employee@6a33ee9b  

通过观察结果可以看出,在第一次查询id为1的Employee对象时执行了一条select语句,但是第二次获取id为1的Employee对象时并没有执行select语句,因为此时一级缓存也就是SqlSession缓存中已经缓存了id为1的Employee对象,Mybatis直接从缓存中将对象取出来,并没有再次去查询数据库,所以第二次也就没有执行select语句

执行方法类二:

[java] 
view plain  
copy

  1. public void testCache1(){  
  2.     //使用工厂类获得SqlSession对象  
  3.     SqlSession sqlSession = ZSqlSessionFactory.getSqlSession();  
  4.     //获得EmployeeMapping对象  
  5.     EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);  
  6.     Employee employee1 = employeeMapper.selectEmployeeById(1);  
  7.     System.out.println(employee1);  
  8.     //执行delete操作  
  9.     employeeMapper.deleteEmployeeById(4);  
  10.     //commit提交  
  11.     sqlSession.commit();  
  12.     //再次查询id为1的Employee对象,因为DML操作会清空sqlSession缓存,所以会再次执行select语句  
  13.     Employee employee2 = employeeMapper.selectEmployeeById(1);  
  14.     System.out.println(employee2);  
  15.     sqlSession.close();  
  16. }  

运行之后的结果:

[plain] 
view plain  
copy

  1. 10:06:52.691 [main] DEBUG org.apache.ibatis.logging.LogFactory – Logging initialized using ‘class org.apache.ibatis.logging.log4j2.Log4j2Impl’ adapter.  
  2. 2017-04-05 10:06:53,129 DEBUG [com.zxc.mapper.EmployeeMapper.selectEmployeeById] – ==>  Preparing: SELECT * FROM employee WHERE id = ?   
  3. 2017-04-05 10:06:53,186 DEBUG [com.zxc.mapper.EmployeeMapper.selectEmployeeById] – ==> Parameters: 1(Integer)  
  4. 2017-04-05 10:06:53,215 DEBUG [com.zxc.mapper.EmployeeMapper.selectEmployeeById] – <==      Total: 1  
  5. com.zxc.domain.Employee@6a33ee9b  
  6. 2017-04-05 10:06:53,216 DEBUG [com.zxc.mapper.EmployeeMapper.deleteEmployeeById] – ==>  Preparing: DELETE FROM employee WHERE id = ?   
  7. 2017-04-05 10:06:53,216 DEBUG [com.zxc.mapper.EmployeeMapper.deleteEmployeeById] – ==> Parameters: 4(Integer)  
  8. 2017-04-05 10:06:53,217 DEBUG [com.zxc.mapper.EmployeeMapper.deleteEmployeeById] – <==    Updates: 1  
  9. 2017-04-05 10:06:53,219 DEBUG [com.zxc.mapper.EmployeeMapper.selectEmployeeById] – ==>  Preparing: SELECT * FROM employee WHERE id = ?   
  10. 2017-04-05 10:06:53,219 DEBUG [com.zxc.mapper.EmployeeMapper.selectEmployeeById] – ==> Parameters: 1(Integer)  
  11. 2017-04-05 10:06:53,221 DEBUG [com.zxc.mapper.EmployeeMapper.selectEmployeeById] – <==      Total: 1  
  12. com.zxc.domain.Employee@1e2fce9c  

结果分析:在第一次查询id为1的employee对象时执行了一条select语句,接下来执行了一个delete并commit操作,Mybatis为了保证缓存中存储的是最新消息,会清空SqlSession缓存。当第二次获取id为1的User对象时一级缓存也就是SqlSession缓存中并没有缓存任何对象,所以Mybatis再次执行语句去查询id为1的Exployee对象。

这里有兴趣的朋友可以试试delete操作之后不commit()操作,看Mybatis是否会再次执行查询语句。

执行方法类三:

[java] 
view plain  
copy

  1. public void testCache1(){  
  2.     //使用工厂类获得SqlSession对象  
  3.     SqlSession sqlSession = ZSqlSessionFactory.getSqlSession();  
  4.     //获得EmployeeMapping对象  
  5.     EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);  
  6.     Employee employee1 = employeeMapper.selectEmployeeById(1);  
  7.     System.out.println(employee1);  
  8.     //关闭一级缓存  
  9.     sqlSession.close();  
  10.     //再次访问,需要再次获取一级缓存,然后才能查找数据,否则会抛出异常  
  11.     sqlSession = ZSqlSessionFactory.getSqlSession();  
  12.     //再次获得EmployeeMapper对象  
  13.     employeeMapper = sqlSession.getMapper(EmployeeMapper.class);          
  14.     Employee employee2 = employeeMapper.selectEmployeeById(1);  
  15.     System.out.println(employee2);  
  16.     sqlSession.close();  
  17. }  

运行结果:

[plain] 
view plain  
copy

  1. 17:12:03.705 [main] DEBUG org.apache.ibatis.logging.LogFactory – Logging initialized using ‘class org.apache.ibatis.logging.log4j2.Log4j2Impl’ adapter.  
  2. 2017-04-05 17:12:04,151 DEBUG [com.zxc.mapper.EmployeeMapper.selectEmployeeById] – ==>  Preparing: SELECT * FROM employee WHERE id = ?   
  3. 2017-04-05 17:12:04,204 DEBUG [com.zxc.mapper.EmployeeMapper.selectEmployeeById] – ==> Parameters: 1(Integer)  
  4. 2017-04-05 17:12:04,230 DEBUG [com.zxc.mapper.EmployeeMapper.selectEmployeeById] – <==      Total: 1  
  5. com.zxc.domain.Employee@3016f5a0  
  6. 2017-04-05 17:12:04,231 DEBUG [com.zxc.mapper.EmployeeMapper.selectEmployeeById] – ==>  Preparing: SELECT * FROM employee WHERE id = ?   
  7. 2017-04-05 17:12:04,231 DEBUG [com.zxc.mapper.EmployeeMapper.selectEmployeeById] – ==> Parameters: 1(Integer)  
  8. 2017-04-05 17:12:04,233 DEBUG [com.zxc.mapper.EmployeeMapper.selectEmployeeById] – <==      Total: 1  
  9. com.zxc.domain.Employee@77763895  

结果分析:在第一次查询id为1的User对象时执行了一条select语句,接下来调用SqlSession的close()方法,该方法会关闭SqlSession缓存,当第二次获取id为1的Employee对象时一级缓存也就是SqlSession缓存是一个新的对象,其中并没有缓存任何对象,所以Mybatis再次执行select语句去查询id为1的Employee对象。

二级缓存:

二级缓存是mapper级别的缓存,使用二级缓存时,多个SqlSession使用同一个Mapper的sql语句去操作数据库,得到的数据会存在二级缓存区域,它同样是使用HashMapper进行数据存储,相比一级缓存SqlSession,二级缓存的范围更大,多个SqlSession可以共用二级缓存,二级缓存是跨SqlSession的。

二级缓存是多个SqlSession共享的,其作用域是mapper的同一个namespace,不同的SqlSession两次执行相同的namespace下的sql语句,且向sql中传递的参数也相同,即最终执行相同的sql语句,则第一次执行完毕会将数据库中查询的数据写到缓存(内存),第二次查询时会从缓存中获取数据,不再去底层数据库查询,从而提高查询效率。

Mybatis默认没有开启二级缓存,需要在setting全局参数中配置开启二级缓存。

在mybatis-config.xml中配置:

[html] 
view plain  
copy

  1. <settings>          
  2.     <setting name=“cacheEnabled” value=“true”/>  
  3. </settings>  

cacheEnabled的value为true表示在此配置文件下开启二级缓存,该属性默认为false。

在EmployeeMapper.xml中配置:

[html] 
view plain  
copy

  1. <!– 开启当前mapper的namespace下的二级缓存 –>  
  2. <cache eviction=“LRU” flushInterval=“60000” size=“512” readOnly=“true”/>  

以上配置创建了一个LRU缓存,并每隔60秒刷新,最大存储512个对象,而且返回的对象被认为是只读。

cache元素用来开启当前mapper的namespace下的二级缓存,该元素的属性设置如下:

  • flushInterval:刷新间隔,可以被设置为任意的正整数,而且它们代表一个合理的毫秒形式的时间段,默认情况下是不设置的,也就是没有刷新间隔,缓存仅仅调用语句时刷新。
  • size:缓存数目,可以被设置为任意正整数,要记住你的缓存对象数目和你运行环境可用内存资源数目,默认值是1024.
  • readOnly:只读,属性可以被设置为true或false,只读的缓存会给所有调用者返回缓存对象的相同实例,因此这些对象不能被修改。这提供了很重要的性能优势,可读写的缓存会返回缓存对象的拷贝(通过序列化),这会慢一些,但是安全,因此默认是false。
  • eviction:收回策略,默认为LRU,有如下几种:
    • LRU:最近最少使用的策略,移除最长时间不被使用的对象。
    • FIFO:先进先出策略,按对象进入缓存的顺序来移除它们。
    • SOFT:软引用策略,移除基于垃圾回收器状态和软引用规则的对象。
    • WEAK:弱引用策略,更积极地移除基于垃圾收集器状态和弱引用规则的对象。

注意:使用二级缓存时,与查询结果映射的java对象必须实现java.io.Serializable接口的序列化和反序列化操作,如果存在父类,其成员都需要实现序列化接口,实现序列化接口是为了对缓存数据进行序列化和反序列化操作,因为二级缓存数据存储介质多种多样,不一定在内存,有可能是硬盘或者远程服务器。

执行方法类四:

[java] 
view plain  
copy

  1. public void testCache1(){  
  2.     //使用工厂类获得SqlSession对象  
  3.     SqlSession sqlSession = ZSqlSessionFactory.getSqlSession();  
  4.     //获得EmployeeMapping对象  
  5.     EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);  
  6.     Employee employee1 = employeeMapper.selectEmployeeById(1);  
  7.     System.out.println(employee1);  
  8.     //关闭一级缓存  
  9.     sqlSession.close();  
  10.     //再次访问,需要再次获取一级缓存,然后才能查找数据,否则会抛出异常  
  11.     sqlSession = ZSqlSessionFactory.getSqlSession();  
  12.     //再次获得EmployeeMapper对象  
  13.     employeeMapper = sqlSession.getMapper(EmployeeMapper.class);  
  14.     //再次查询id为1的Employee对象,因为DML操作会清空sqlSession缓存,所以会再次执行select语句  
  15.     Employee employee2 = employeeMapper.selectEmployeeById(1);  
  16.     System.out.println(employee2);  
  17.     sqlSession.close();  
  18. }  

运行结果:

[plain] 
view plain  
copy

  1. 18:18:10.743 [main] DEBUG org.apache.ibatis.logging.LogFactory – Logging initialized using ‘class org.apache.ibatis.logging.log4j2.Log4j2Impl’ adapter.  
  2. 2017-04-05 18:18:10,920 DEBUG [com.zxc.mapper.EmployeeMapper] – Cache Hit Ratio [com.zxc.mapper.EmployeeMapper]: 0.0  
  3. 2017-04-05 18:18:11,169 DEBUG [com.zxc.mapper.EmployeeMapper.selectEmployeeById] – ==>  Preparing: SELECT * FROM employee WHERE id = ?   
  4. 2017-04-05 18:18:11,224 DEBUG [com.zxc.mapper.EmployeeMapper.selectEmployeeById] – ==> Parameters: 1(Integer)  
  5. 2017-04-05 18:18:11,252 DEBUG [com.zxc.mapper.EmployeeMapper.selectEmployeeById] – <==      Total: 1  
  6. com.zxc.domain.Employee@2934ad41  
  7. 2017-04-05 18:18:11,254 DEBUG [com.zxc.mapper.EmployeeMapper] – Cache Hit Ratio [com.zxc.mapper.EmployeeMapper]: 0.5  
  8. com.zxc.domain.Employee@2934ad41  

若禁用当前select语句的二级缓存,修改EmployeeMapper.xml如下:

[html] 
view plain  
copy

  1. <select id=“selectEmployeeById” parameterType=“int” resultType=“com.zxc.domain.Employee” useCache=“false”>  

此时运行结果:

[plain] 
view plain  
copy

  1. 18:20:30.418 [main] DEBUG org.apache.ibatis.logging.LogFactory – Logging initialized using ‘class org.apache.ibatis.logging.log4j2.Log4j2Impl’ adapter.  
  2. 2017-04-05 18:20:30,861 DEBUG [com.zxc.mapper.EmployeeMapper.selectEmployeeById] – ==>  Preparing: SELECT * FROM employee WHERE id = ?   
  3. 2017-04-05 18:20:30,916 DEBUG [com.zxc.mapper.EmployeeMapper.selectEmployeeById] – ==> Parameters: 1(Integer)  
  4. 2017-04-05 18:20:30,943 DEBUG [com.zxc.mapper.EmployeeMapper.selectEmployeeById] – <==      Total: 1  
  5. com.zxc.domain.Employee@54d5da26  
  6. 2017-04-05 18:20:30,945 DEBUG [com.zxc.mapper.EmployeeMapper.selectEmployeeById] – ==>  Preparing: SELECT * FROM employee WHERE id = ?   
  7. 2017-04-05 18:20:30,945 DEBUG [com.zxc.mapper.EmployeeMapper.selectEmployeeById] – ==> Parameters: 1(Integer)  
  8. 2017-04-05 18:20:30,947 DEBUG [com.zxc.mapper.EmployeeMapper.selectEmployeeById] – <==      Total: 1  
  9. com.zxc.domain.Employee@7116778b  

结果分析:第一次查询时,虽然关闭了SqlSession也就是一级缓存,但是因为启用了二级缓存,第一次查询到的结果被保存到二级缓存中,Mybatis在一级缓存中没有找到id为1的Employee对象,就会去二级缓存中查找,所以不会再次执行select语句。当禁用了二级缓存,又关闭了SqlSession,第二次查询mybatis就会再一次执行一次select语句。

小结:本文介绍了Mybatis的缓存机制,包括一级缓存SqlSession和二级缓存mapper,使用缓存可以最大程度低减轻数据查询压力,提高数据库性能。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/106228.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • 改名了,一个新的开始

    怕什么真理无穷进一步有近一步的欢喜这个是我电脑桌面壁纸1又有一段时间没来这里了,看了上次发文的日期是2021年10月31日,已经快过去三个月了。上次发文还是2021现在已经到2022年了,…

  • SQL分页查询_Sql根据某个字段分页

    SQL分页查询_Sql根据某个字段分页SQL分页查询:背景​ 在公司的系统中有一个平台是做配置管理的就是所谓的CRUD的平台,但是点击后进去到页面第一次看到的是一次查询的页面(点击页面自动的触发查询的功能)后面就可以你的CRUD的操作是给运营的同事来操作的,但是一般的是我们数据量比较的少的业务是之间查询出来所有的数据,直接返回给前端的让他自己做分页的,但是有一些数据量达到上万级别的时候,不能让他们乱搞了,…

  • Iterative Shrinkage Thresholding Algorithm

    Iterative Shrinkage Thresholding AlgorithmIterativeShrinkageThresholdingAlgorithm(ISTA)

  • idea2019激活码(已测有效)

    idea2019激活码(已测有效),https://javaforall.cn/100143.html。详细ieda激活码不妨到全栈程序员必看教程网一起来了解一下吧!

  • pytest运行_python缓存机制

    pytest运行_python缓存机制前言pytest运行完用例之后会生成一个.pytest_cache的缓存文件夹,用于记录用例的ids和上一次失败的用例。方便我们在运行用例的时候加上–lf和–ff参数,快速运行上一

  • SDN网络下有哪些SDN交换机选择?「建议收藏」

    随着SDN技术的发展,SDN网络架构迎来了历史性的变革,SDN被认为是下一代网络变革的重要方向。而SDN交换机作为一款高性能,高密度的下一代交换机,为SDN大规模的商用部署和下一代网络技术的创新应用,起到了助推加速的作用。那么,什么是SDN网络,基于SDN技术的SDN交换机又是什么?面对不同类型的SDN交换机,我们又应该如何选择?接下来,本文将为您解答。SDN网络是什么SDN(SoftwareDefinedNetwork)即“软件定义网络”,SDN网络存在的目的是为了简化过多的网络结构,通过..

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号