• myBaits缓存


    转自:https://blog.csdn.net/zhongzh86/article/details/50019511

    9. Mybatis 缓存

       正如大多数持久层框架一样,MyBatis 同样提供了一级缓存二级缓存的支持

    1 1. 一级缓存: 基于PerpetualCache 的 HashMap本地缓存,其存储作用域为 Session,当 Session flush 或 close 之后,该Session中的所有 Cache 就将清空。
    2 2. 二级缓存与一级缓存其机制相同,默认也是采用 PerpetualCache,HashMap存储,不同在于其存储作用域为 Mapper(Namespace),并且可自定义存储源,如 Ehcache。
    3 3. 对于缓存数据更新机制,当某一个作用域(一级缓存Session/二级缓存Namespaces)的进行了 C/U/D 操作后,默认该作用域下所有 select 中的缓存将被clear。
     

    9.1 Mybatis的一级缓存

    9.1.1  数据表准备

     1 /*用户表*/
     2 drop table if exists user;
     3 create table user(
     4     id int primary key auto_increment,
     5     username varchar(50) unique,
     6     password varchar(100),
     7     nickname varchar(50),
     8     salt varchar(100),
     9     locked boolean
    10 )engine=InnqDB default charset=utf8;
     

    9.1.2  User实体类准备

     
     1 package com.mscncn.batis.model;
     2 
     3 
     4 public class User {
     5     private int id;
     6     private int age;
     7     private String userName;
     8     private String userAddress;
     9     public int getId() {
    10         return id;
    11     }
    12     public void setId(int id) {
    13         this.id = id;
    14     }
    15     public String getUserName() {
    16         return userName;
    17     }
    18     public void setUserName(String userName) {
    19         this.userName = userName;
    20     }
    21     public String getUserAddress() {
    22         return userAddress;
    23     }
    24     public void setUserAddress(String userAddress) {
    25         this.userAddress = userAddress;
    26     }
    27     public int getAge() {
    28         return age;
    29     }
    30     public void setAge(int age) {
    31         this.age = age;
    32     }
    33     
    34 }
     

    9.1.3 UserMapper.java

    1 public interface UserMapper {
    2 
    3 
    4 
    5     public User getUserById(int id);
    6 
    7 
    8 
    9 }
     

    9.1.4 UserMapper.xml

     1 <?xml version="1.0" encoding="UTF-8" ?> 
     2 <!DOCTYPE mapper 
     3     PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 
     4     "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> 
     5 <!-- 这里namespace必须是PostsMapper接口的路径,不然要运行的时候要报错 “is not known to the MapperRegistry”--> 
     6 <mapper namespace="com.mscncn.batis.mapper.UserMapper"> 
     7     <!-- 这儿的resultType是配置在mybatis-config.xml中得别名 -->
     8     <select id="getUserById" parameterType="int" resultType="User">
     9             select * from user where id=#{id}
    10     </select>
    11 </mapper>
     

    9.1.5 测试

     1 @Test 
     2     public void testgetUserById() { 
     3        SqlSession sqlSession = sqlSessionFactory.openSession(); 
     4        try { 
     5                    UserMapper mapper = sqlSession.getMapper(UserMapper.class); 
     6                    //注意,重写User的toString方法
     7                    User u1=mapper.getUserById(1);
     8                    System.out.println(u1);
     9                    User u2=mapper.getUserById(1);
    10                    System.out.println(u2);
    11            sqlSession.commit();//这里一定要提交,不然数据进不去数据库中 
    12        } finally { 
    13            sqlSession.close(); 
    14        } 
    15     }
     

    9.1.6 测试结果

       从以上结果中可以看出,两次调用getUserById方法,但是只有一次查询数据库的过程,这种现象产生的原因就是mybatis的一级缓存,并且一级缓存是默认开启的。

     

    9.2  Mybatis的二级缓存

     

    9.2.1 没有开启Mybatis二级缓存之前,测试

     
     1  @Test 
     2     public void testCache2() { 
     3        SqlSession sqlSession = sqlSessionFactory.openSession(); 
     4        SqlSession sqlSession2 = sqlSessionFactory.openSession(); 
     5        try { 
     6                    UserMapper mapper = sqlSession.getMapper(UserMapper.class); 
     7                    UserMapper mapper2 = sqlSession2.getMapper(UserMapper.class); 
     8                    //注意,重写User的toString方法
     9                    User u1=mapper.getUserById(1);
    10                    System.out.println(u1);
    11                    User u2=mapper2.getUserById(1);
    12                    System.out.println(u2);
    13            sqlSession.commit();//这里一定要提交,不然数据进不去数据库中 
    14        } finally { 
    15            sqlSession.close(); 
    16        } 
    17     }
     

      测试结果:

      两个session,分别查询id为1 的 User ,那么mybatis与数据库交互了两次,这样说明mybatis现在没有开启二级缓存,需要我们手动的开启。

     

    9.2.2 User.java

        实体类实现可序列化接口:

     1 public class User implements Serializable {...} 
        如果实体类不实现可序列化接口,使用二级缓存,那么会报下列异常:
     1 org.apache.ibatis.cache.CacheException: Error serializing object. Cause: java.io.NotSerializableException:    

    9.2.3 Mybatis 配置文件

        默认配置:

    <settings> 
    <setting name="cacheEnabled" value="true"/>
    </settings>

     必须开启缓存配置,才能使用mybatis的二级缓存,不然不能使用

     

    9.2.4 Mybatis二级缓存测试

     1 @Test 
     2     public void testCache2() { 
     3         SqlSession sqlSession = sqlSessionFactory.openSession(); 
     4         SqlSession sqlSession2 = sqlSessionFactory.openSession(); 
     5         try { 
     6                     UserMapper mapper = sqlSession.getMapper(UserMapper.class); 
     7                     UserMapper mapper2 = sqlSession2.getMapper(UserMapper.class); 
     8                     //注意,重写User的toString方法
     9                     User u1=mapper.getUserById(1);
    10                     sqlSession.commit();
    11                     System.out.println(u1);
    12                     User u2=mapper2.getUserById(1);
    13                     System.out.println(u2);
    14             sqlSession.commit();//这里一定要提交,不然数据进不去数据库中 
    15         } finally { 
    16             sqlSession.close(); 
    17         } 
    18     }
     

       这儿需要注意,必须使用的是两个不同的session,并且第一个session必须提交才能使用二级缓存(二级缓存必须提交前面的session,现在还没有找到原因)

    9.2.5 测试结果

    9.3 总结

      mybatis 一级缓存:默认开启

      1. 必须同一个session,如果session对象已经close()过了就不能用了

      2. 查询条件必须一致

      3. 没有执行过session.cleanCache();清理缓存

      4. 没有执行过增删改操作(这些操作都会清理缓存) 

     mybatis 二级缓存: 

    mybatis-config.xml 中默认配置

     <settings>
      <setting name="cacheEnabled" value="true" /> 
      </settings>

     必须手动开启在Mapper.xml中添加

     <cache/> 有默认的参数值

     1 <cache />
     2 <?xml version="1.0" encoding="UTF-8" ?> 
     3 <!DOCTYPE mapper 
     4     PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 
     5     "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> 
     6 <!-- 这里namespace必须是PostsMapper接口的路径,不然要运行的时候要报错 “is not known to the MapperRegistry”--> 
     7 <mapper namespace="com.mscncn.batis.mapper.UserMapper"> 
     8     <cache />
     9     <!-- 这儿的resultType是配置在mybatis-config.xml中得别名 -->
    10     <select id="getUserById" parameterType="int" resultType="User">
    11             select * from user where id=#{id}
    12     </select>
    13 </mapper>
     

    1. 映射语句文件中的所有select语句将会被缓存。 

    2. 映射语句文件中的所有insert,update和delete语句会刷新缓存。 

    3. 缓存会使用Least Recently Used(LRU,最近最少使用的)算法来收回。 

    4. 缓存会根据指定的时间间隔来刷新。 

    5. 缓存会存储1024个对象

     

    <cache 

    eviction="FIFO"  //回收策略为先进先出

    flushInterval="60000" //自动刷新时间60s

    size="512" //最多缓存512个引用对象

    readOnly="true"/> //只读

     

  • 相关阅读:
    改不改,这是一个问题
    连载:面向对象的葵花宝典:思考、技巧与实践(39)
    Oracle压缩总结2— 估计表压缩效应
    CSDN markdown 编辑 第五章 UML
    Arcgis for Javascript之featureLayer图和属性互操作性
    bzoj 2437 [Noi2011]兔子和鸡蛋 [二分图匹配]
    “jquery于each方法和选择”学习笔记
    安卓模拟器错误: Could not open
    软路试--就像一棵树活着
    2014第21周二
  • 原文地址:https://www.cnblogs.com/sharpest/p/5669530.html
Copyright © 2020-2023  润新知