框架: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);
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 + '\'' + '}'; } }
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>
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); }
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); } }
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>
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)); } }
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)); }
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(只读)属性可以被设置为 true 或 false。只读的缓存会给所有调用者返回缓 存对象的相同实例。因此这些对象不能被修改。这提供了很重要的性能优势。可读写的缓存 会返回缓存对象的拷贝(通过序列化) 。这会慢一些,但是安全,因此默认是 false。 -->
yexiangyang
moyyexy@gmail.com