章来源:听云博客

一致: 查询缓存

  Mybatis提供查询缓存,用于减轻数据压力,提高数据库压力。

  Mybatis提供一级缓存和二级缓存。

  统计 1

  于操作数据库时欲结构SqlSession对象,在靶吃生出一个数据结构(HashMap)用于缓存数据。

  不同的SqlSession之间的缓存数据区域是并行不影响的。

  Mybatis一级缓存的作用域是跟一个SqlSession,在与一个sqlSession中简单破实践同一之sql语句,第一糟实行完毕会用数据库中询问的多少形容到缓存(内存),第二不好会打缓存中获取数据将不再从数据库查询,从而加强查询效率。当一个sqlSession结束晚该sqlSession中的一级缓存也就未有了。Mybatis默认开启一级缓存。

   Mybatis二级缓存是大抵单SqlSession共享的,其作用域是mapper的同一个namespace,不同的sqlSession两差实行同一namespace下的sql语句都为sql中传递参数为一致便最终实施同一之sql语句,第一破实施完毕会拿数据库中询问的数量形容到缓存(内存),第二潮见面起缓存中获取数据将不再由数据库查询,从而增强查询效率。Mybatis默认没有开二级缓存需要以setting全局参数中布置开启二级缓存。

     
 这是自我去年十一回去就算开始计划之实验,重装系统之后用QQ存储文件的文件夹放到了本人之备份盘里,
QQ会将您的聊天记录和图纸分别储存,而且群组和挚友也是分手存放于少单文件夹里之,好友G:\Tencent
file\<your qq number>\Image\C2C,群组G:\Tencent file\<your
qq
number>\Image\Group。尽量保证电脑长时开机,并且保证QQ一直在线,这样,每当QQ群里经受到信息后,图片就叫封存在了而的当地硬盘上。所以有人在群里爆了照再撤回其实是足以找到的,偷笑偷笑,只要找到Group文件夹里最新的照片就是哼了。

  1、一级缓存

  统计 2

  第一坏发起查询,先去寻找缓存中是否发id为1底用户信息,如果没,从数据库被查询用户信息。

  得到用户信息,将用户信息囤积到一级缓存中。

  第二不善发起查询用户id为1之用户信息,先去缓存中是否发id为1底用户信息,缓存中有,直接由缓存中获用户信息。

  如果SqlSession去实施commit操作(执行插入、更新、删除),清空SqlSession中之一级缓存。目的是为让缓存中储存的是流行的音讯,避免脏读。

  Mybatis默认支持一级缓存,不待以配置文件被布置。

  Mybatis内部存储缓存使用一个HashMap,key为hashCode+sqlId+Sql语句。value为从询问出来映射生成的java对象。

  应用场景:

  统计 3

统计 4

  2、二级缓存

  统计 5

  SqlSession1去查询用户id为1底用户信息,查询及用户信息会将查询数据存储到二级缓存中。

  SqlSession2失查询用户id为1的用户信息,去缓存中搜索是否是多少,如果在直接打缓存中取出数据。

  二级缓存区域是基于mapper的namespace划分的,相同namespace的mapper查询数据在和一个区域,如果下mapper代理方法每个mapper的namespace都不可同日而语,此时可以清楚吧二级缓存区域是依据mapper划分。

老是查询会先打缓存区域搜索,如果找不至打数据库查询,查询到数量以数据勾勒副缓存。

  Mybatis内部存储缓存使用一个HashMap,key为hashCode+sqlId+Sql语句。value为从询问出来映射生成的java对象

  sqlSession执行insert、update、delete等操作commit提交后会清空缓存区域。

  启二级缓存

  1.以基本配置文件mybatis-config.xml中加入

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

描述

允许值

默认值

cacheEnabled

对在此配置文件下的所有cache 进行全局性开/关设置。

true false

true

     2.
比方以你的Mapper映射文件中补充加一行:  <cache /> ,表示这mapper开启二级缓存。

 
 3.二级缓存需要查询结果映射的pojo对象实现java.io.Serializable接口实现序列化和反序列化操作,注意要在父类、成员pojo都得实现序列化接口。

  为了以缓存数据取出执行反序列化,因为二级缓存存储介质多种多样,不自然当内存。

  剥夺二级缓存:

  于statement中安装useCache=false可以禁用当前select语句之二级缓存,即每次查询都见面产生sql去查询,默认情况是true,即该sql使用二级缓存。

<select id="findOrderListResultMap" resultMap="ordersUserMap" useCache="false">

  刷新缓存(就是清空缓存)

  设置statement配置中的flushCache=”true” 属性,默认情况下也true即刷新缓存,如果更改化false则非见面刷新。使用缓存时如手动修改数据库表中的查询数据会油然而生脏读。

<insert id="insertUser" parameterType="cn.itcast.mybatis.po.User" flushCache="true">

  动用场景

  对于访问多的查询请求都用户指向查询结果实时性要求未愈,此时不过采取mybatis二级缓存技术降低数据库访问量,提高访问速度,业务场景比如:耗时可比高的统计分析sql、电话账单查询sql等。

     
实现方式如下:通过安装刷新间隔时间,由mybatis每隔一段时间自动清空缓存,根据数量变化频率设置缓存刷新间隔flushInterval,比如安为30分钟、60分钟、24时等,根据要求要自然。

  局限性

  mybatis二级缓存对细粒度的多少级别的苏存实现不好,比如如下需求:对商品信息进行缓存,由于商品信息查询访问量大,但是要求用户每次都能查询最新的商品信息,此时使采取mybatis的二级缓存就无法兑现当一个货变化时只是刷新该商品的缓存信息若非刷新其它商品的消息,因为mybaits的二级缓存区域因mapper为单位划分,当一个商品信息变化会将具备商品信息的缓存数据全部清空。解决此类问题亟需在工作层根据需要对数据有针对性缓存。

     
 随着图片越来越多,QQ会把多年来缓存的图样整理及一个新的公文夹里去,每届4000张图的时节就是整一次于。我加以了90几近个QQ群,一半上述是千人群,6单月之后我之文书夹就变成了此法。

二:案例

统计 6

源码介绍:

1.Student.java

统计 7统计 8

package cn.zhang.entity;

import java.util.Date;

/**
 * 学生实体类
 * 
 */
public class Student {

    private Integer stuno;
    private String stuname;
    private Integer stuage;
    private Date studate;

    public String toString() {
        return "Student [stuno=" + stuno + ", stuname=" + stuname + ", stuage="
                + stuage + ", studate=" + studate + "]";
    }

    public Integer getStuno() {
        return stuno;
    }

    public void setStuno(Integer stuno) {
        this.stuno = stuno;
    }

    public String getStuname() {
        return stuname;
    }

    public void setStuname(String stuname) {
        this.stuname = stuname;
    }

    public Integer getStuage() {
        return stuage;
    }

    public void setStuage(Integer stuage) {
        this.stuage = stuage;
    }

    public Date getStudate() {
        return studate;
    }

    public void setStudate(Date studate) {
        this.studate = studate;
    }

}

View Code

2.MybatisUtil.java

统计 9统计 10

package cn.zhang.util;

import java.io.IOException;
import java.io.Reader;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

/**
 * 工具类
 * 
 */
public class MybatisUtil {

    private static String config = "mybatis-config.xml";
    static Reader reader;
    static {
        try {
            reader = Resources.getResourceAsReader(config);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    private static SqlSessionFactory factory = new SqlSessionFactoryBuilder()
            .build(reader);

    // 提供一个可以获取到session的方法
    public static SqlSession getSession() throws IOException {

        SqlSession session = factory.openSession();
        return session;
    }
}

View Code

3.StudentDao.java

统计 11统计 12

package cn.zhang.dao;

import java.io.IOException;
import cn.zhang.entity.Student;

public interface StudentDao {


    /**
     * @return
     * @throws IOException
     */
    public Student findAll(Integer sid) throws IOException;


    public int insertStudent(Student stu);


}

View Code

4.StudentDAO.xml

统计 13统计 14

<?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="cn.zhang.dao.StudentDao">

    <!-- 查询所有 -->
    <select id="findAll" resultType="Student">
        select * from student where stuno=#{stuno}
    </select>
    <!-- 新增 -->
    <insert id="insertStudent">
    insert into student(stuname,stuage,studate) value(#{stuname},#{stuage},#{studate})
    </insert>

</mapper>

View Code

5.mybatis-config.xml

统计 15统计 16

<?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>
    <!-- 配置别名 -->
    <typeAliases>
        <!--方式一: 按类型名定制别名 -->
        <typeAlias type="cn.zhang.entity.Student" alias="Student" />
        <!--方式二: 拿当前指定包下的简单类名作为别名 -->
        <!-- <package name="cn.zhang.entity"/> -->
    </typeAliases>
    <environments default="mysql">

        <environment id="oracle">
            <!-- 使用jdbc的事务 -->
            <transactionManager type="JDBC" />
            <!-- 使用自带的连接池 -->
            <dataSource type="POOLED">
            <!-- 我用的Oracle数据库 -->
                <property name="driver" value="oracle.jdbc.driver.OracleDriver" />
                <property name="url" value="jdbc:oracle:thin:@localhost:1521:orcl" />
                <property name="username" value="zhangzong" />
                <property name="password" value="123" />
            </dataSource>
        </environment>


        <environment id="mysql">
            <!-- 使用jdbc的事务 -->
            <transactionManager type="JDBC" />
            <!-- 使用自带的连接池 -->
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver" />
                <property name="url" value="jdbc:mysql://localhost:3306/y2161" />
                <property name="username" value="root" />
                <property name="password" value="root" />
            </dataSource>
        </environment>


    </environments>
    <mappers>
        <mapper resource="cn/zhang/dao/StudentDAO.xml" />
    </mappers>
</configuration>

View Code

6.MyTest.java

统计 17统计 18

package cn.zhang.test;

import java.io.IOException;
import java.util.Date;

import org.apache.ibatis.session.SqlSession;
import org.junit.Before;
import org.junit.Test;
import cn.zhang.dao.StudentDao;
import cn.zhang.entity.Student;
import cn.zhang.util.MybatisUtil;

public class MyTest {

    StudentDao dao;

    @Before
    public void initData() throws IOException {
        SqlSession session = MybatisUtil.getSession();
        dao = session.getMapper(StudentDao.class);// 使用了getMapper()方法获得dao实例
    }

    /**
     * 查询所有学生
     * 
     * @throws IOException
     */
    @Test
    public void findAll() throws IOException {
        //查询
        Student stu = dao.findAll(1);
        System.out.println(stu);

        //新增--执行commit操作(执行插入、更新、删除),清空SqlSession中的一级缓存
        /*
        Student student=new Student();
        student.setStuage(12);
        student.setStuname("垃圾");
        student.setStudate(new Date());
        dao.insertStudent(student);
        */

        //查询---一级缓存中
        Student stu2 = dao.findAll(1);
        System.out.println(stu2);

    }
}

View Code

 

     
 缓存了近乎7独G的图形,一共十万五千摆设。

统计 19 

     
 这次不讨论聚合和图片分类的题目,我们简要的统计一下直接从图文件所携带的音。这些图片一共来三种植要的格式,
JPEG,PNG,GIF,通常就是,照片,截图,表情包~~

     
 比例如下:

统计 20 

     
 除了简便易行的档次统计吗,我们还得依据图片的创建时间来统计信息,当然在报到QQ的同一起来,也会见为大气的受图片而致一个时序列及图片数出现极值。

     
 时间序列尺度在宏观,分钟,和天的变化情况就算明白了。

统计 21

统计 22 

     
 哦,周末人们在网上还于平日掉了一半,可能是活泼的人头丢了,也恐怕是虎虎有生气的时间不见了,但是自己道,大家以家睡到12点之可能性还老一点,谁受我加的且是工科群。

     
 从每天的多少中得以看到,竟然到了1点基本上夜在才收。然后第二天6点差不多陆续起床,12碰同时开去用去了,有微人口尚于突击,等等,图像上都亮的不可磨灭。

     
 再拘留一样年吃之多少,好像周期性很显眼,一到礼拜大家就歇了呗?那么,二月五哀号左右我们于关乎吧?怎么那么小?原来是以过年。那怎么来一定量龙是0?好吧,我当来回的列车上。

     
 等等,如果PNG代表截图,那可能代表大家以讨论问题。如果GIF多片,可能代表大家以斗图水群啊!我接近找到了你们无做事偷懒的暧昧!让咱们来分别看一下老三种植图片的动态变化。

统计 23 

     
 过年的时大家又欣赏拿磕的照分享到群里!

     
 那么到的呢?

统计 24 

     
 左侧是总数,右侧是比例,大家在星期,更少讨论工作,也要命少聊天,竟然来四分之一之人挑选外出过自己之星期!让自家充分是惊讶,只有我一个总人口会晤自然醒么?

     
 对了咱们还有图片的红火高信息:

统计 25 

     
 加了对数之后的布状况,貌似看不发出什么,那直用散点吧

统计 26 

     
 几及线若隐若现的典范,连起来看好了

统计 27 

     
 这生知那些线是呀了,是手机屏幕尺寸及电脑屏幕大小。斜线虽是屏幕的增长宽比啦。也殊易看到那些屏幕占了市场之主流。那1:1之?有这种屏幕??应该是截图的当儿截的图长宽比在1荒谬右变吧,看到条线也是最为小的。

     
 顺便看了一下那些图是极端常用的。腾讯为了减少图片于网络流上的浪费,对于md5一样的图纸,他们于聊天记录里的名是均等的!值得一提的凡,一摆gif动图的率先帧如果与某某静态的jpge图片一样吧,那么她们的名吧是一律的,基于此规律,统计了瞬间29个文本夹下起次数最多之图形前三叫作,竟然是是:

统计 28统计 29统计 30 
 

     
 果然要表情包,可能重爱影响大家就的心气吧。帧数最多的凡

统计 31 

     
 贪吃蛇。两幅的就算都是bling bling的色了

     
 同事根据图片大小,把持有16*16邻近的图形都过滤出来就得博同套表情包。

统计 32 

     
 好了此文到此结束,这次未讨论了多的模式识别和监察上之类的事物,希望大家为会以想不交的地方获得想不到的结果,希望会针对各位有启发。看了晚望你们为能给个这样的神色。

   
  统计 33

     
 THE END

 

原稿链接:http://blog.tingyun.com/web/article/detail/300