框架:Mybatis缓存使用介绍

一、Mybatis缓存分一级缓存,二级缓存,简单来说,

       1、一级缓存,指在同一SqlSession中,SqlSession未关闭,两次查询sql语句相同,第二次不会查询数据库,直接从缓存中获取,默认开启一级缓存

       2、二级缓存,指在不同SqlSession中,SqlSession未关闭,两次查询sql语句相同,第二次不会查询数据库,直接从缓存中获取,需要启动配置,

并且缓存的对象需要实现java.io.Serializable接口。

二、测试并使用缓存     

      1、添加依赖包,参考上篇文章 Mybatis+mysql入门使用

      2、初始化数据库和初始数据,以mysql为例

DROP DATABASE IF EXISTS moy_mybatis;
CREATE DATABASE moy_mybatis CHARACTER SET UTF8;
USE moy_mybatis;

DROP TABLE  IF EXISTS t_test;

CREATE TABLE t_test(
    id int(11) AUTO_INCREMENT,
    create_time DATE comment '创建时间',
    modify_time DATE comment '修改时间',
    content VARCHAR (50) comment '内容',
    PRIMARY KEY (id)
);

INSERT INTO t_test (create_time,modify_time,content)
            VALUES (NOW(),NOW(),1);
View Code

      3、新建实体类TestEntity

package com.moy.mybatis3.entity;

import java.io.Serializable;
import java.util.Date;

/**
 * [Project]:moy-gradle-project  <br/>
 * [Email]:moy25@foxmail.com  <br/>
 * [Date]:2018/2/20  <br/>
 * [Description]:  <br/>
 *
 * @author YeXiangYang
 */
public class TestEntity implements Serializable{
    private Integer id;
    private Date createTime;
    private Date modifyTime;
    private String content;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public Date getCreateTime() {
        return createTime;
    }

    public void setCreateTime(Date createTime) {
        this.createTime = createTime;
    }

    public Date getModifyTime() {
        return modifyTime;
    }

    public void setModifyTime(Date modifyTime) {
        this.modifyTime = modifyTime;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    @Override
    public String toString() {
        return "TestEntity{" +
                "id=" + id +
                ", createTime=" + createTime +
                ", modifyTime=" + modifyTime +
                ", content='" + content + '\'' +
                '}';
    }
}
View Code

      4、新建实体对应配置文件Test.xml

<?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.moy.mybatis3.mapper.TestMapper">
    <!--开启二级缓存-->
    <!--<cache></cache>-->
    <select id="get" parameterType="int" resultType="TestEntity">
        SELECT id,create_time as createTime,modify_time as modifyTime ,content
        FROM t_test WHERE id=#{id}
    </select>
</mapper>
View Code

      5、编写接口TestMapper

package com.moy.mybatis3.mapper;

import com.moy.mybatis3.entity.TestEntity;

import java.io.Serializable;
import java.util.List;

/**
 * [Project]:moy-gradle-project  <br/>
 * [Email]:moy25@foxmail.com  <br/>
 * [Date]:2018/2/20  <br/>
 * [Description]:  <br/>
 *
 * @author YeXiangYang
 */
public interface TestMapper {

    TestEntity get(Serializable id);
}
View Code

      6、为了方便测试,编写一个获取SqlSession的工具类Mybatis3Utils

package com.moy.mybatis3.utils;

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

import java.io.IOException;
import java.io.Reader;
import java.util.Objects;

/**
 * [Project]:moy-gradle-project  <br/>
 * [Email]:moy25@foxmail.com  <br/>
 * [Date]:2018/2/19  <br/>
 * [Description]:  <br/>
 *
 * @author YeXiangYang
 */
public abstract class Mybatis3Utils {

    public static final SqlSessionFactory sqlSessionFactory;
    public static final ThreadLocal<SqlSession> sessionThread = new ThreadLocal<>();

    static {
        try {
            Reader reader = Resources.getResourceAsReader("mybatis-config.xml");
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public static SqlSession getCurrentSqlSession() {
        SqlSession sqlSession = sessionThread.get();
        if (Objects.isNull(sqlSession)) {
            sqlSession = sqlSessionFactory.openSession();
            sessionThread.set(sqlSession);
        }
        return sqlSession;
    }

    public static void closeCurrentSession() {
        SqlSession sqlSession = sessionThread.get();
        if (Objects.nonNull(sqlSession)) {
            sqlSession.close();
        }
        sessionThread.set(null);
    }
}
View Code

      7、新建mybatis配置信息文件mybatis-config.xml

<?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>
        <!--打印sql日志去控制台-->
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>

    <typeAliases>
        <package name="com.moy.mybatis3.entity"/>
    </typeAliases>

    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://127.0.0.1:3306/moy_mybatis?useSSL=false"/>
                <property name="username" value="root"/>
                <property name="password" value="123"/>
            </dataSource>
        </environment>
    </environments>

    <mappers>
        <mapper resource="mapper/Test.xml"></mapper>
    </mappers>
</configuration>     
View Code

      8、编写测试类TestMapperTest,测试一级缓存,控制台只会第一次查询打印sql日志,二次不会打印sql日志

package com.moy.mybatis3.mapper;

import com.moy.mybatis3.entity.TestEntity;
import com.moy.mybatis3.utils.Mybatis3Utils;
import org.apache.ibatis.session.SqlSession;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

import static org.junit.Assert.*;

/**
 * [Project]:moy-gradle-project  <br/>
 * [Email]:moy25@foxmail.com  <br/>
 * [Date]:2018/2/20  <br/>
 * [Description]:  <br/>
 *
 * @author YeXiangYang
 */
public class TestMapperTest {

    SqlSession sqlSession;
    TestMapper testMapper;

    @Before
    public void before() {
        sqlSession = Mybatis3Utils.getCurrentSqlSession();
        testMapper = sqlSession.getMapper(TestMapper.class);
    }

    @After
    public void after() {
        Mybatis3Utils.closeCurrentSession();
    }

    @Test
    public void testFirstCache() {
        // 一级缓存(默认开启)
        // 在同一session中,session未关闭,
        // 两次查询sql语句相同,第二次不会查询数据库
        System.out.println("一级缓存 sqlSession--->" + sqlSession);
        System.out.println(testMapper.get(1));
        System.out.println(testMapper.get(1));
    }
}
View Code

     9、测试二级缓存,取消Test.xml的<cache></cache>注释,添加测试方法

    @Test
    public void testSecondCache() {
        // 二级缓存 (需要开启缓存设置)
        // 在不同session中,
        // 两次查询sql语句相同,第二次不会查询数据库
        System.out.println("二级缓存 sqlSession--->" + sqlSession);
        System.out.println(testMapper.get(1));
        Mybatis3Utils.closeCurrentSession();

        sqlSession = Mybatis3Utils.getCurrentSqlSession();
        testMapper = sqlSession.getMapper(TestMapper.class);
        System.out.println("二级缓存 sqlSession--->" + sqlSession);
        System.out.println(testMapper.get(1));
    }
View Code

     10、使用<cache></cache>元素配置缓存介绍

<!-- 
<cache eviction="FIFO" flushInterval="60000" size="512" readOnly="false"/>
创建了一个 FIFO 缓存,并每隔 60 秒刷新,存数结果对象或列表的 512 个引用,而且返回的对象被认为是只读的,因此在不同线程中的调用者之间修改它们会 导致冲突。可用的收回策略有以下几种, 默认的是 LRU:
1. LRU – 最近最少使用的:移除最长时间不被使用的对象。 
2. FIFO – 先进先出:按对象进入缓存的顺序来移除它们。 
3. SOFT – 软引用:移除基于垃圾回收器状态和软引用规则的对象。 
4. WEAK – 弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。
flushInterval:刷新间隔时间,可以被设置为任意的正整数,单位毫秒。默认情况是不设置,也就是没有刷新间隔,缓存仅仅调用语句时刷新。
size:内存资源数目,可以被设置为任意正整数。默认值是1024。
readOnly(只读)属性可以被设置为 truefalse。只读的缓存会给所有调用者返回缓 存对象的相同实例。因此这些对象不能被修改。这提供了很重要的性能优势。可读写的缓存 会返回缓存对象的拷贝(通过序列化) 。这会慢一些,但是安全,因此默认是 false-->
View Code

 

yexiangyang

moyyexy@gmail.com


 

posted @ 2018-02-21 21:03  墨阳  阅读(194)  评论(0编辑  收藏  举报