Mybatis缓存

一级缓存(默认是开启的)

一级缓存是就是sqlsession,在sqlsession中有一个数据区域,是map结构,这个区域就是一级缓存区域,一级缓存中的key是由sql语句、条件、statement等信息组成的一个唯一值,一级缓存中的value,就是查询出的结果对象。

原理:当第一次查询id为1的用户时,会将查询结果写入sqlsession一级缓存区域的map中,此时如果再查询一次id为1的用户,就会直接查询一级缓存中的数据(不用查询数据库,只有一个sql语句)。但如果在两次查询中有修改、添加、删除用户执行了commit时,则会清空一级缓存中的数据,此时在查询id为1的用户,则会重新查询数据库(两条sql查询语句)

例1: 两次查询没有修改、删除、添加commit

1.编写测试类,调用usermapper中的查询方法,usermapper中的的查询方法前边有,这里不多写

public class Demo12 {
    
    /**
     //     * session级别一级缓存,默认开启
     //     * @throws IOException
     //     */
    @Test
    public void test11() throws IOException {
        InputStream is= Resources.getResourceAsStream("SqlMapConfig.xml");
//        1.通过SqlSessionFactoryBuilder创建SqlSessionFactory会话工厂。
        SqlSessionFactory factory= new SqlSessionFactoryBuilder().build(is);
        //2.会话
        SqlSession session=factory.openSession();
//3.通过会话获取dao接口(mapper)
        UserMapper mapper=session.getMapper(UserMapper.class);
        User user1=mapper.findUserById(1);
        System.out.println("user1:"+user1);
        User user2=mapper.findUserById(1);
        System.out.println("user2:"+user2);
        session.commit();
        session.close();
    }
}

2.查询结果,只有一条sql语句

DEBUG [main] - ==>  **Preparing: SELECT * from user where id=?** 
DEBUG [main] - ==> Parameters: 1(Integer)
DEBUG [main] - <==      Total: 1
user1:User{id=1, username='王五', sex='2', birthday=null, address='null'}
user2:User{id=1, username='王五', sex='2', birthday=null, address='null'}

例2: 两次查询之间有修改、删除、添加commit

1.编写测试类,调用usermapper中的查询方法和保存方法,usermapper中的的查询和保存方法前边有,这里不多写

public class Demo12 {

    /**
     //     * session级别一级缓存,默认开启
     //     *保存,删除,更新,一级缓存数据会自动更新,会执行sql语句
     //     * @throws IOException
     //     */
    @Test
    public void test11() throws IOException {
        InputStream is= Resources.getResourceAsStream("SqlMapConfig.xml");
//        1.通过SqlSessionFactoryBuilder创建SqlSessionFactory会话工厂。
        SqlSessionFactory factory= new SqlSessionFactoryBuilder().build(is);
        //2.会话
        SqlSession session=factory.openSession();
//3.通过会话获取dao接口(mapper)
        UserMapper mapper=session.getMapper(UserMapper.class);
        User user1=mapper.findUserById(1);
        System.out.println("user1:"+user1);

        //保存用户
        mapper.save(new User("广东","1",null,"广东"));
        User user2=mapper.findUserById(1);
        System.out.println("user2:"+user2);
    }
}

2.查询结果,有两条查询sql语句

DEBUG [main] - ==>  **Preparing: SELECT * from user where id=?** 
DEBUG [main] - ==> Parameters: 1(Integer)
DEBUG [main] - <==      Total: 1
user1:User{id=1, username='王五', sex='2', birthday=null, address='null'}
DEBUG [main] - ==>  Preparing: insert into user (username,sex,birthday,address) values (?,?,?,?) 
DEBUG [main] - ==> Parameters: 广东(String), 1(String), null, 广东(String)
DEBUG [main] - <==    Updates: 1
DEBUG [main] - ==>  **Preparing: SELECT * from user where id=?** 
DEBUG [main] - ==> Parameters: 1(Integer)
DEBUG [main] - <==      Total: 1
user2:User{id=1, username='王五', sex='2', birthday=null, address='null'}

二级缓存(所有一级缓存共享。需要手动开启)

二级缓存就是同一个namespace下的mapper(sessionFactory),二级缓存中,也有一个map结构,这个区域就是一级缓存区域,一级缓存中的key是有sql语句、条件、statement等信息组成的一个唯一值,一级缓存中的value,就是查询出的结果对象。

原理:将session写入二级缓存中,必须将session关闭才能写入

在这里插入图片描述

实现:

1.在全局配置文件中配置二级缓存总开关

 <settings>
        <!--允许开启二级缓存-->
        <setting name="cacheEnabled" value="true"></setting>
    </settings>

2.在UserMapper中配置二级缓存

 <!--配置二级缓存
      默认使用的是mybatis自带的缓存技术,prepetualCache(永久缓存)
    -->
    <cache></cache>

3.user序列化

public class User  implements Serializable {

案例1:创建三个session,分别查询用户信息

1.编写测试类

 /**
     //     * sessionFactory级别二级缓存,需手动开启
     //     *保存,删除,更新,一级缓存数据会自动更新,会执行sql语句
     //     * @throws IOException
     //     */
    @Test
    public void test12() throws IOException {
        InputStream is= Resources.getResourceAsStream("SqlMapConfig.xml");
//        1.通过SqlSessionFactoryBuilder创建SqlSessionFactory会话工厂。
        SqlSessionFactory factory= new SqlSessionFactoryBuilder().build(is);
        //2.会话
        SqlSession session1=factory.openSession();
        SqlSession session2=factory.openSession();
        SqlSession session3=factory.openSession();
        //3.获取dao
       UserMapper mapper1= session1.getMapper(UserMapper.class);
       UserMapper mapper2= session2.getMapper(UserMapper.class);
       UserMapper mapper3= session3.getMapper(UserMapper.class);

       User user1=mapper1.findUserById(1);
        System.out.println("user1"+user1);
        //session关闭之后,才能写入二级缓存中
        session1.close();

        User user2=mapper2.findUserById(1);
        System.out.println("user2"+user2);
        session1.close();

        User user3=mapper3.findUserById(1);
        System.out.println("user3"+user3);
    }

2.结果,只有一条查询语句

DEBUG [main] - ==>  **Preparing: SELECT * from user where id=?** 
DEBUG [main] - ==> Parameters: 1(Integer)
DEBUG [main] - <==      Total: 1
user1User{id=1, username='王五', sex='2', birthday=null, address='null'}
DEBUG [main] - Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@5f71c76a]
DEBUG [main] - Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@5f71c76a]
DEBUG [main] - Returned connection 1601292138 to pool.
DEBUG [main] - Cache Hit Ratio [com.szl.mapper.UserMapper]: 0.5
user2User{id=1, username='王五', sex='2', birthday=null, address='null'}
DEBUG [main] - Cache Hit Ratio [com.szl.mapper.UserMapper]: 0.6666666666666666
user3User{id=1, username='王五', sex='2', birthday=null, address='null'}

案例2:创建三个session,分别查询用户信息,在查询之间有保存提交

1.编写测试类

 /**
     //     * sessionFactory级别二级缓存,需手动开启
     //     *保存,删除,更新,一级缓存数据会自动更新,会执行sql语句
     //     * @throws IOException
     //     */
    @Test
    public void test12() throws IOException {
        InputStream is= Resources.getResourceAsStream("SqlMapConfig.xml");
//        1.通过SqlSessionFactoryBuilder创建SqlSessionFactory会话工厂。
        SqlSessionFactory factory= new SqlSessionFactoryBuilder().build(is);
        //2.会话
        SqlSession session1=factory.openSession();
        SqlSession session2=factory.openSession();
        SqlSession session3=factory.openSession();
        //3.获取dao
       UserMapper mapper1= session1.getMapper(UserMapper.class);
       UserMapper mapper2= session2.getMapper(UserMapper.class);
       UserMapper mapper3= session3.getMapper(UserMapper.class);

       User user1=mapper1.findUserById(1);
        System.out.println("user1"+user1);
        //session关闭之后,才能写入二级缓存中
        session1.close();
        //保存
        mapper3.save(new User("斗门雨神","1",null,"广东"));
        session3.commit();
        session3.close();

        User user2=mapper2.findUserById(1);
        System.out.println("user2"+user2);
        session2.close();

    }

2.结果,有两条查sql语句

DEBUG [main] - ==>  **Preparing: SELECT * from user where id=?** 
DEBUG [main] - ==> Parameters: 1(Integer)
DEBUG [main] - <==      Total: 1
user1User{id=1, username='王五', sex='2', birthday=null, address='null'}
DEBUG [main] - ==>  **Preparing: insert into user (username,sex,birthday,address) values (?,?,?,?)** 
DEBUG [main] - ==> Parameters: 斗门雨神(String), 1(String), null, 广东(String)
DEBUG [main] - ==>  **Preparing: SELECT * from user where id=?** 
DEBUG [main] - ==> Parameters: 1(Integer)
DEBUG [main] - <==      Total: 1
user2User{id=1, username='王五', sex='2', birthday=null, address='null'}

mybatis整合ehcache缓存

mybatis本身是一个持久性层框架,不是专门的缓存框架,所以对缓存的实现不够好,不能支持分布式。
ehcache是一个分布式的缓存框架。
分布式:系统为了提高性能,通常会对系统采用分布式部署(集群式部署)——有M服务器,每个服务器上跑相同的项目,如果每台服务器的最大访问量是N,则此时就可以有MN个访问用户。

整合思路:

Cache是一个接口,它的默认实现的是mybatis的perpetualCache,如果想要整合mybatis的二级缓存,则实现Cache接口即可。
在这里插入图片描述

整合步骤:

1.添加jar包,放到lib中
在这里插入图片描述

2.设置映射文件中的cache标签

  <!--配置二级缓存
      默认使用的是mybatis自带的缓存技术,perpetualCache(永久缓存)
      type可以改成ehcache缓存
    -->
    <cache type="org.mybatis.caches.ehcache.EhcacheCache"></cache>

3.在src下添加ehcache配置文件
在这里插入图片描述
 maxElementsInMemory :设置基于内存的缓存中可存放的对象最大数目
 eternal:设置对象是否为永久的,true表示永不过期,此时将忽略
 timeToIdleSeconds 和 timeToLiveSeconds属性; 默认值是false
 timeToIdleSeconds:设置对象空闲最长时间,以秒为单位, 超过这个时间,对象过期。当对象过期时,EHCache会把它从缓存中清除。如果此值为0,表示对象可以无限期地处于空闲状态。
 timeToLiveSeconds:设置对象生存最长时间,超过这个时间,对象过期。如果此值为0,表示对象可以无限期地存在于缓存中. 该属性值必须大于或等于 timeToIdleSeconds 属性值
 overflowToDisk:设置基于内在的缓存中的对象数目达到上限后,是否把溢出的对象写到基于硬盘的缓存中
 flashInterval:设置二级缓存刷新间隔,过了这个时间就清空(毫秒)
 diskPersistent 当jvm结束时是否持久化对象 true false 默认是false
 diskExpiryThreadIntervalSeconds 指定专门用于清除过期对象的监听线程的轮询时间
memoryStoreEvictionPolicy - 当内存缓存达到最大,有新的element加入的时候, 移除缓存中element的策略。默认是LRU(最近最少使用),可选的有LFU(最不常使用)和FIFO(先进先出)

4.测试结果同Mybatis二级缓存测试结果

禁用指定方法的二级缓存

直接在mapper.XML文件中要禁用的方法中添加useCache=“false”即可,默认是true

 <select id="findUserById" parameterType="int" resultType="com.szl.model.User" **useCache="false"**>
           SELECT * from user where id=#{id}
    </select>

结果:禁用查询缓存后,sql语句有两条

DEBUG [main] - ==>  Preparing: SELECT * from user where id=? 
DEBUG [main] - ==> Parameters: 1(Integer)
DEBUG [main] - <==      Total: 1
user1User{id=1, username='王五', sex='2', birthday=null, address='null'}

DEBUG [main] - ==>  Preparing: SELECT * from user where id=? 
DEBUG [main] - ==> Parameters: 1(Integer)
DEBUG [main] - <==      Total: 1
user2User{id=1, username='王五', sex='2', birthday=null, address='null'}

刷新缓存

 <!--默认插入、更新、删除会清空缓存,默认情况下flushCache=true”,如果设置为false,则上述方法就不会清空二级缓存-->
    <insert id="save" parameterType="com.szl.model.User" flushCache="false">
        insert  into user (username,sex,birthday,address)
        values (#{username},#{sex},#{birthday},#{address})
    </insert>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值