前言

说起mybatis的一级缓存和二级缓存我特意问了几个身边的朋友他们平时会不会用,结果没有一个人平时业务场景中用。 好吧,那我暂且用来学习源码吧。一级缓存我个人认为也确实有些鸡肋,mybatis默认开启一级缓存,支持在同一个会话(sqlsession)同一个statement执行两次,则第二次会默认会使用第一次创建的缓存对象。

二级缓存前一篇粗略介绍了下,默认使用内存对象【PerpetualCache】内部维护一个HashMap对象来存储。那么先来看几张图片【图片来自一位朋友,文章最后参考连接我会挂出作者博客】

MyBatis缓存设计及二级缓存工作模式

从上面三张图中我们得出结论,一级缓存是sqlsession级别、二级缓存是Mapper级别。mybatis定义了【Cache】接口,支持自定义缓存,同时还支持集成第三方缓存库,现在为了更细粒度的控制缓存,更多的集成【ehcache】、【redis】。

那么mybatis的二级缓存主要是在Executor对象上来做文章,当mybatis发现你在mybatis.xml配置文件中设置了cacheEnabled=true时,mybatis在创建sqlsession时创建Executor对象,同时会对Executor加上装饰者【CacheExecutor】。CacheExecutor对于查询请求,会判断application级别的二级缓存是否有缓存结果,如果有查询结果则直接返回,如果没有再交给查询器Executor实现类,也就是【SimpleExecutor】来执行查询。再就是缓存结果,返回给用户。

贴出SmpleExecutor源码:

/**
* Copyright 2009-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.ibatis.executor; import org.apache.ibatis.cursor.Cursor;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.logging.Log;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.apache.ibatis.transaction.Transaction; import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Collections;
import java.util.List; /**
* @author Clinton Begin
*/
public class SimpleExecutor extends BaseExecutor { public SimpleExecutor(Configuration configuration, Transaction transaction) {
super(configuration, transaction);
} @Override
public int doUpdate(MappedStatement ms, Object parameter) throws SQLException {
Statement stmt = null;
try {
Configuration configuration = ms.getConfiguration();
StatementHandler handler = configuration.newStatementHandler(this, ms, parameter, RowBounds.DEFAULT, null, null);
stmt = prepareStatement(handler, ms.getStatementLog());
return handler.update(stmt);
} finally {
closeStatement(stmt);
}
} @Override
public <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
Statement stmt = null;
try {
Configuration configuration = ms.getConfiguration();
StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);
stmt = prepareStatement(handler, ms.getStatementLog());
return handler.<E>query(stmt, resultHandler);
} finally {
closeStatement(stmt);
}
} @Override
protected <E> Cursor<E> doQueryCursor(MappedStatement ms, Object parameter, RowBounds rowBounds, BoundSql boundSql) throws SQLException {
Configuration configuration = ms.getConfiguration();
StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, null, boundSql);
Statement stmt = prepareStatement(handler, ms.getStatementLog());
return handler.<E>queryCursor(stmt);
} @Override
public List<BatchResult> doFlushStatements(boolean isRollback) throws SQLException {
return Collections.emptyList();
} private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {
Statement stmt;
Connection connection = getConnection(statementLog);
stmt = handler.prepare(connection, transaction.getTimeout());
handler.parameterize(stmt);
return stmt;
} }

  那么,缓存起来的数据怎么过期呢,这也是我这篇文章重点关心的。一般流量不大的站点,数据由后台维护,使用二级缓存足够了。先来看全局配置文件,配置只关心一点:cacheEnabled=true。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<settings>
<!--开启二级缓存-->
<setting name="cacheEnabled" value="true"/>
</settings>
<typeAliases>
<typeAlias alias="User" type="com.autohome.model.User" />
</typeAliases> <mappers>
<mapper resource="mapper/UserMapper.xml" />
</mappers> </configuration>

Mapper.xml

这里配置Cache对象。这里的eviction参数提到几个算法策略:

     LRU:(Least Recently Used),最近最少使用算法,即如果缓存中容量已经满了,会将缓存中最近做少被使用的缓存记录清除掉,然后添加新的记录;

FIFO:(First in first out),先进先出算法,如果缓存中的容量已经满了,那么会将最先进入缓存中的数据清除掉;

 Scheduled:指定时间间隔清空算法,该算法会以指定的某一个时间间隔将Cache缓存中的数据清空;

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--命名空间和接口保持一致-->
<mapper namespace="com.autohome.dao.UserMapper"> <!--
eviction LRU
flushInterval缓存时间,以毫秒为单位
size缓存大小
readOnly如果为false的话,缓存对象必须是可序列化的-->
<cache eviction="LRU"
type="org.apache.ibatis.cache.impl.PerpetualCache"
flushInterval="120000"
size="1024"
readOnly="true"/> <select id="listAllUser" resultType="User">
select * from t_userinfo
</select> </mapper>

配图看demo

第一次查询是36条数据,我配置缓存是2分钟。然后再insert一条,你再刷新页面数据不变。等两分钟。。。。

总结

OK,所谓的存在即合理吧,适合不适合取决于你的业务场景。mybatis也提供了接口以便扩展。小流量、数据量小使用mybatis二级缓存足以。

参考

http://blog.csdn.net/luanlouis/article/details/41408341

MyBatis从入门到放弃七:二级缓存原理分析的更多相关文章

  1. MyBatis:二级缓存原理分析

    MyBatis从入门到放弃七:二级缓存原理分析 前言 说起mybatis的一级缓存和二级缓存我特意问了几个身边的朋友他们平时会不会用,结果没有一个人平时业务场景中用. 好吧,那我暂且用来学习源码吧.一 ...

  2. MyBatis基础入门《十六》缓存

    MyBatis基础入门<十六>缓存 >> 一级缓存 >> 二级缓存 >> MyBatis的全局cache配置 >> 在Mapper XML文 ...

  3. Mybatis 一级缓存和二级缓存原理区别 (图文详解)

    Java面试经常问到Mybatis一级缓存和二级缓存,今天就给大家重点详解Mybatis一级缓存和二级缓存原理与区别@mikechen Mybatis缓存 缓存就是内存中的数据,常常来自对数据库查询结 ...

  4. 【Web技术】276- WebView缓存原理分析和应用

    前言 混合式开发,在产品体验以及页面加载速度的体验上已经非比以往的.今日早读文章由@unclechen分享. 正文从这开始- 一.背景 现在的App开发,或多或少都会用到Hybrid模式,到了WebV ...

  5. MyBatis从入门到放弃六:延迟加载、一级缓存、二级缓存

    前言 使用ORM框架我们更多的是使用其查询功能,那么查询海量数据则又离不开性能,那么这篇中我们就看下mybatis高级应用之延迟加载.一级缓存.二级缓存.使用时需要注意延迟加载必须使用resultMa ...

  6. Mybatis源码分析之Cache二级缓存原理 (五)

    一:Cache类的介绍 讲解缓存之前我们需要先了解一下Cache接口以及实现MyBatis定义了一个org.apache.ibatis.cache.Cache接口作为其Cache提供者的SPI(Ser ...

  7. MyBatis功能点一应用:二级缓存整合redis

    Mybatis提供了默认的cache实现PerpetualCache,那为什么还要整合第三方的框架redis?因为Mybatis提供的cache实现为单机版,无法实现分布式存储(即本机存储的数据,其他 ...

  8. MyBatis从入门到精通(七):MyBatis动态Sql之choose,where,set标签的用法

    最近在读刘增辉老师所著的<MyBatis从入门到精通>一书,很有收获,于是将自己学习的过程以博客形式输出,如有错误,欢迎指正,如帮助到你,不胜荣幸! 本篇博客主要讲解如何使用choose, ...

  9. Hibernate二级缓存原理

    缓存:缓存是什么,解决什么问题? 位于速度相差较大的两种硬件/软件之间的,用于协调两者数据传输速度差异的结构,均可称之为缓存Cache.缓存目的:让数据更接近于应用程序,协调速度不匹配,使访问速度更快 ...

随机推荐

  1. 基于Entity Framework的自定义分页,增删改的通用实现

    简介 之前写个一个基于Dapper的分页实现,现在再来写一个基于Entity Framework的分页实现,以及增删改的通用实现. 代码 还是先上代码:https://github.com/jinwe ...

  2. nopCommerce 3.9 大波浪系列 之 事件机制(生产者、消费者)

    一.nop事件机制简介 应用场景:客户支付成功后,需要发送短信.邮件告知客户订单支付成功(短信.邮件由不同模块实现) 实现方法: 1.定义支付成功OrderPaidEvent事件. 2.定义短信,邮箱 ...

  3. Python开发【笔记】:单线程下执行多个定时任务

    单线程多定时任务 前言:公司业务需求,实例当中大量需要启动定时器的操作:大家都知道python中的定时器用的是threading.Timer,每当启动一个定时器时,程序内部起了一个线程,定时器触发执行 ...

  4. (转)Linux端口nmap和netstat命令

    场景:弄不清楚端口和服务的关系,总觉得这个命令很有用但是还不清楚如何使用 1 linux端口与服务 1.1 安全概述 网络传输安全.操作系统安全.应用软件安全构成了整个网络应用的安全:其中应用软件安全 ...

  5. Accord.NET_Naive Bayes Classifier

    我们这个系列主要为了了解并会使用Accord.NET中机器学习有关算法,因此主要关注的是算法针对的的问题,算法的使用.所以主要以代码为主,通过代码来学习,在脑海中形成一个轮廓.下面就言归正传,开始贝叶 ...

  6. java 线程之concurrent中的常用工具 CyclicBarrier

    一.CyclicBarrier CyclicBarrier是一个同步辅助类,它允许一组线程互相等待,直到到达某个公共屏障点 (common barrier point).在涉及一组固定大小的线程的程序 ...

  7. 《MVC实现用户权限》

    用树形的结构显示权限的结构,树形结构的用的是jquery的控件 1. 赋给用户一个userid,在用户角色表将用户和角色关联起来,在角色权限表中将角色和权限对应起来,权限表中存储的是菜单栏的名称. 2 ...

  8. 【RegExp】JavaScript中正则表达式判断匹配规则以及常用方法

    字符串是编程时涉及到的最多的一种数据结构,对字符串进行操作的需求几乎无处不在. 正则表达式是一种用来匹配字符串的强有力的武器.它的设计思想是用一种描述性的语言来给字符串定义一个规则,凡是符合规则的字符 ...

  9. 双向循环链表(C语言描述)(四)

    下面以一个电子英汉词典程序(以下简称电子词典)为例,应用双向循环链表.分离数据结构,可以使逻辑代码独立于数据结构操作代码,程序结构更清晰,代码更简洁:电子词典的增.删.查.改操作分别对应于链表的插入. ...

  10. How to create a jump server in AWS VPC

    本来是写的Word文档,给其他国家的同时看的,所以一开始就是英文写的,也没打算翻译成为中文了,顺便抱怨下,网上资料找了很久的资料都没有看到介绍怎么在单机环境下搭建RD Gateway的,写本文的目的是 ...