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,使用缓存可以最大程度低减轻数据查询压力,提高数据库性能。

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

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

(0)
上一篇 2022年4月23日 下午12:40
下一篇 2022年4月23日 下午1:00


相关推荐

  • phpstorm 激活码生成(破解版激活)

    phpstorm 激活码生成(破解版激活),https://javaforall.net/100143.html。详细ieda激活码不妨到全栈程序员必看教程网一起来了解一下吧!

    2022年3月16日
    125
  • tcpdump抓包命令详解_tcpdump抓udp包命令详解

    tcpdump抓包命令详解_tcpdump抓udp包命令详解linux抓包-tcpdump命令:enp4s0f0—ifconfig—>网卡名称-s0—->不限制抓包的大小port25228—->只抓取服务器上25228端口的数据流量-whk2.pcap—>保存的文件名称-v—>显示抓包的大小数字

    2022年8月20日
    10
  • 正在接入或无法接入认证服务器(服务器未运行怎么解决)

    迷你版云服务器未启动内容精选换一换企业主机安全(HostSecurityService,HSS)是提升服务器整体安全性的服务,通过主机管理、风险防御、入侵检测、安全运营、网页防篡改功能,可全面识别并管理云服务器中的信息资产,实时监测云服务器中的风险,降低服务器被入侵的风险。使用主机安全需要在云服务器中安装Agent。安装Agent后,您的云服务器将受到HSS云端防护中企业主机安全(Host…

    2022年4月17日
    61
  • java 队列方法详解「建议收藏」

    java 队列方法详解「建议收藏」一、队列支持的方法(Queue) throwexception returnspecialvalue insert add 1、增加元素不能为null 2、其他异常,比如有界队列 offer 1、元素不能为null 2、实现内部调用addF…

    2022年7月7日
    27
  • debian引导文件配置

    debian引导文件配置

    2026年3月14日
    2
  • CentOS安装/卸载Anaconda(图文详解)

    CentOS安装/卸载Anaconda(图文详解)众所周知的原因 从官网下载 Anaconda 非常慢 因此为了加速下载 这里我们采取清华源下载 不过下载前想要查看具体的版本信息 还是推荐从官网查看 这里我们以项目要用到的 2021 05 版本为例 输入 这里我们刚刚安装下载的文件 文件名与下载后缀相同 bashAnaconda 2021 05 Linux x86 64 sh 然后按 ENTER 即可 Please pressENTERto 接下来进入安装协议部分 一直按 ENTER 即可在安装许可的最后出现

    2026年3月19日
    1

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

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