mybatis的缓存机制是怎么样的?
1.缓存,其存储作用域为 Session,当 Session flush 或 close 之后,该Session中的所有 Cache 就将清空。
2. 二级缓存与一级缓存其机制相同,默认也是采用 PerpetualCache,HashMap存储,不同在于其存储作用域为 Mapper(Namespace),并且可自定义存储源,如 Ehcache。
3. 对于缓存数据更新机制,当某一个作用域(一级缓存Session/二级缓存Namespaces)的进行了 C/U/D 操作后,默认该作用域下所有 select 中的缓存将被clear。
mybatis的一级缓存作用就是在同一个session过程中,将会对相同数据的存取不通过数据库,而是通过缓存机制提高效率,看测试代码
<img src="https://pic3.zhimg.com/50/c225e22b0d00f5903b3626009228767e_hd.jpg" data-rawwidth="307" data-rawheight="347" class="content_image" width="307">
import java.io.IOException;
import java.io.InputStream;import junit.framework.TestCase;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 org.junit.Test;import com.guowuxin.mybatis.mapper.UserMapper;
import com.guowuxin.mybatis.model.User;/*用户表
drop table if exists user;
create table user(id int primary key auto_increment,username varchar(50) unique,password varchar(100),useraddress varchar(50)
);
insert into user values(1,"guowuxin","guowuxin","beijing");
insert into user values(1,"guoxiaoming","guowuxin","beijing");
*///如果两次查询都是查询1 将只会发送一条sql语句到数据库,否则将是2条sql语句public class TestClass extends TestCase{public static SqlSessionFactory sqlSessionFactoy;static{String resource = "mybatis-config.xml";try {InputStream inputStream = Resources.getResourceAsStream(resource);sqlSessionFactoy = new SqlSessionFactoryBuilder().build(inputStream);} catch (IOException e) {e.printStackTrace();}}@Test public void testgetUserById() { SqlSession sqlSession = sqlSessionFactoy.openSession(); try { UserMapper mapper = sqlSession.getMapper(UserMapper.class); User u1=mapper.getUserById(1);System.out.println(u1);User u2=mapper.getUserById(1);System.out.println(u2);sqlSession.commit();} finally { sqlSession.close(); } }
}
package com.guowuxin.mybatis.mapper;import com.guowuxin.mybatis.model.User;//通过面向接口的mybatis编程方式,需要保证方法名和配置文件中的id名称一致
public interface UserMapper {public User getUserById(int id);
}
package com.guowuxin.mybatis.model;public class User {private int id;private int age;private String userName;private String userAddress;public int getId() {return id;}public void setId(int id) {this.id = id;}public String getUserName() {return userName;}public void setUserName(String userName) {this.userName = userName;}public String getUserAddress() {return userAddress;}public void setUserAddress(String userAddress) {this.userAddress = userAddress;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}@Overridepublic String toString(){final StringBuilder builder = new StringBuilder();builder.append("id=").append(id).append(",");builder.append("age=").append(age).append(",");builder.append("userName=").append(userName).append(",");builder.append("userAddress=").append(userAddress).append(".");return builder.toString();}
}
log4j.rootLogger=DEBUG,Console
ˆ†
#Console
log4j.appender.Console=org.apache.log4j.ConsoleAppender
log4j.appender.Console.layout=org.apache.log4j.PatternLayout
log4j.appender.Console.layout.ConversionPattern=%d %t %-5p (%c) - %m%nlog4j.logger.com.ibatis=DEBUG
log4j.logger.com.ibatis.common.jdbc.SimpleDataSource=DEBUG
log4j.logger.com.ibatis.common.jdbc.ScriptRunner=DEBUG
log4j.logger.com.ibatis.sqlmap.engine.impl.SqlMapClientDelegate=DEBUG
log4j.logger.java.sql.Connection=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG
<?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 alias="User" type="com.guowuxin.mybatis.model.User" /></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/guowuxin" /><property name="username" value="root" /><property name="password" value="admin" /></dataSource></environment></environments><mappers><mapper resource="UserMapper.xml" /></mappers></configuration>
<?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">
<!-- 这里namespace必须是PostsMapper接口的路径,不然要运行的时候要报错 “is not known to the MapperRegistry”-->
<mapper namespace="com.guowuxin.mybatis.mapper.UserMapper"> <!-- 这儿的resultType是配置在mybatis-config.xml中得别名 --><select id="getUserById" parameterType="int" resultType="User">select * from user where id=#{id}</select>
</mapper>
结果:
....................
2016-02-24 20:12:37,568 main DEBUG (com.guowuxin.mybatis.mapper.UserMapper.getUserById) - ooo Using Connection [com.mysql.jdbc.JDBC4Connection@3b1d04]
2016-02-24 20:12:37,568 main DEBUG (com.guowuxin.mybatis.mapper.UserMapper.getUserById) - ==> Preparing: select * from user where id=?
2016-02-24 20:12:37,586 main DEBUG (com.guowuxin.mybatis.mapper.UserMapper.getUserById) - ==> Parameters: 1(Integer)
id=1,age=0,userName=guowuxin,userAddress=beijing.
id=1,age=0,userName=guowuxin,userAddress=beijing.
2016-02-24 20:12:37,593 main DEBUG (org.apache.ibatis.transaction.jdbc.JdbcTransaction) - Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@3b1d04]
2016-02-24 20:12:37,593 main DEBUG (org.apache.ibatis.transaction.jdbc.JdbcTransaction) - Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@3b1d04]
2016-02-24 20:12:37,593 main DEBUG (org.apache.ibatis.datasource.pooled.PooledDataSource) - Returned connection 3874052 to pool.
如果取得2个不同的id
.......................
2016-02-24 20:12:57,655 main DEBUG (org.apache.ibatis.datasource.pooled.PooledDataSource) - Created connection 3874052.
2016-02-24 20:12:57,656 main DEBUG (com.guowuxin.mybatis.mapper.UserMapper.getUserById) - ooo Using Connection [com.mysql.jdbc.JDBC4Connection@3b1d04]
2016-02-24 20:12:57,656 main DEBUG (com.guowuxin.mybatis.mapper.UserMapper.getUserById) - ==> Preparing: select * from user where id=?
2016-02-24 20:12:57,664 main DEBUG (com.guowuxin.mybatis.mapper.UserMapper.getUserById) - ==> Parameters: 1(Integer)
id=1,age=0,userName=guowuxin,userAddress=beijing.
2016-02-24 20:12:57,679 main DEBUG (com.guowuxin.mybatis.mapper.UserMapper.getUserById) - ooo Using Connection [com.mysql.jdbc.JDBC4Connection@3b1d04]
2016-02-24 20:12:57,679 main DEBUG (com.guowuxin.mybatis.mapper.UserMapper.getUserById) - ==> Preparing: select * from user where id=?
2016-02-24 20:12:57,679 main DEBUG (com.guowuxin.mybatis.mapper.UserMapper.getUserById) - ==> Parameters: 2(Integer)
id=2,age=0,userName=guoxiaoming,userAddress=beijing.
2016-02-24 20:12:57,679 main DEBUG (org.apache.ibatis.transaction.jdbc.JdbcTransaction) - Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@3b1d04]
2016-02-24 20:12:57,679 main DEBUG (org.apache.ibatis.transaction.jdbc.JdbcTransaction) - Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@3b1d04]
2016-02-24 20:12:57,679 main DEBUG (org.apache.ibatis.datasource.pooled.PooledDataSource) - Returned connection 3874052 to pool.
二级缓存机制指的则是在不同的session之间都可以共享相同的数据内容。
import java.io.IOException;
import java.io.InputStream;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 org.junit.Test;import com.guowuxin.mybatis.mapper.UserMapper;
import com.guowuxin.mybatis.model.User;import junit.framework.TestCase;public class TestTwoCache extends TestCase{public static SqlSessionFactory sqlSessionFactory;static{String resource = "mybatis-config.xml";try {InputStream inputStream = Resources.getResourceAsStream(resource);sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);} catch (IOException e) {e.printStackTrace();}}@Test public void testCache() { SqlSession sqlSession1 = sqlSessionFactory.openSession();SqlSession sqlSession2 = sqlSessionFactory.openSession();try { UserMapper mapper1 = sqlSession1.getMapper(UserMapper.class); User u1=mapper1.getUserById(1);System.out.println(u1);sqlSession1.commit();UserMapper mapper2 = sqlSession2.getMapper(UserMapper.class);User u2=mapper2.getUserById(1);System.out.println(u2);sqlSession2.commit();} finally { sqlSession1.close(); sqlSession2.close();} }
}
在没有开启二级缓存之前,将会执行两次sql语句。
2016-02-24 20:28:10,786 main DEBUG (org.apache.ibatis.datasource.pooled.PooledDataSource) - PooledDataSource forcefully closed/removed all connections.
2016-02-24 20:28:10,850 main DEBUG (org.apache.ibatis.transaction.jdbc.JdbcTransaction) - Openning JDBC Connection
2016-02-24 20:28:11,011 main DEBUG (org.apache.ibatis.datasource.pooled.PooledDataSource) - Created connection 3874052.
2016-02-24 20:28:11,012 main DEBUG (com.guowuxin.mybatis.mapper.UserMapper.getUserById) - ooo Using Connection [com.mysql.jdbc.JDBC4Connection@3b1d04]
2016-02-24 20:28:11,013 main DEBUG (com.guowuxin.mybatis.mapper.UserMapper.getUserById) - ==> Preparing: select * from user where id=?
2016-02-24 20:28:11,030 main DEBUG (com.guowuxin.mybatis.mapper.UserMapper.getUserById) - ==> Parameters: 1(Integer)
id=1,age=0,userName=guowuxin,userAddress=beijing.
2016-02-24 20:28:11,040 main DEBUG (org.apache.ibatis.transaction.jdbc.JdbcTransaction) - Openning JDBC Connection
2016-02-24 20:28:11,154 main DEBUG (org.apache.ibatis.datasource.pooled.PooledDataSource) - Created connection 29420695.
2016-02-24 20:28:11,154 main DEBUG (com.guowuxin.mybatis.mapper.UserMapper.getUserById) - ooo Using Connection [com.mysql.jdbc.JDBC4Connection@1c0ec97]
2016-02-24 20:28:11,154 main DEBUG (com.guowuxin.mybatis.mapper.UserMapper.getUserById) - ==> Preparing: select * from user where id=?
2016-02-24 20:28:11,154 main DEBUG (com.guowuxin.mybatis.mapper.UserMapper.getUserById) - ==> Parameters: 1(Integer)
id=1,age=0,userName=guowuxin,userAddress=beijing.
2016-02-24 20:28:11,154 main DEBUG (org.apache.ibatis.transaction.jdbc.JdbcTransaction) - Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@3b1d04]
2016-02-24 20:28:11,154 main DEBUG (org.apache.ibatis.transaction.jdbc.JdbcTransaction) - Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@3b1d04]
2016-02-24 20:28:11,154 main DEBUG (org.apache.ibatis.datasource.pooled.PooledDataSource) - Returned connection 3874052 to pool.
2016-02-24 20:28:11,154 main DEBUG (org.apache.ibatis.transaction.jdbc.JdbcTransaction) - Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@1c0ec97]
2016-02-24 20:28:11,154 main DEBUG (org.apache.ibatis.transaction.jdbc.JdbcTransaction) - Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@1c0ec97]
2016-02-24 20:28:11,154 main DEBUG (org.apache.ibatis.datasource.pooled.PooledDataSource) - Returned connection 29420695 to pool.
------------------------
在实体类映射文件中加入<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">
<!-- 这里namespace必须是PostsMapper接口的路径,不然要运行的时候要报错 “is not known to the MapperRegistry”-->
<mapper namespace="com.guowuxin.mybatis.mapper.UserMapper"> <!-- 这儿的resultType是配置在mybatis-config.xml中得别名 --><cache /><select id="getUserById" parameterType="int" resultType="User">select * from user where id=#{id}</select>
</mapper>
2016-02-25 10:15:11,162 main DEBUG (org.apache.ibatis.datasource.pooled.PooledDataSource) - Created connection 22522451.
2016-02-25 10:15:11,164 main DEBUG (com.guowuxin.mybatis.mapper.UserMapper.getUserById) - ooo Using Connection [com.mysql.jdbc.JDBC4Connection@157aa53]
2016-02-25 10:15:11,164 main DEBUG (com.guowuxin.mybatis.mapper.UserMapper.getUserById) - ==> Preparing: select * from user where id=?
2016-02-25 10:15:11,182 main DEBUG (com.guowuxin.mybatis.mapper.UserMapper.getUserById) - ==> Parameters: 1(Integer)
id=1,age=0,userName=guowuxin,userAddress=beijing.
2016-02-25 10:15:11,196 main DEBUG (org.apache.ibatis.cache.decorators.LoggingCache) - Cache Hit Ratio [com.guowuxin.mybatis.mapper.UserMapper]: 0.5
id=1,age=0,userName=guowuxin,userAddress=beijing.
2016-02-25 10:15:11,196 main DEBUG (org.apache.ibatis.transaction.jdbc.JdbcTransaction) - Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@157aa53]
2016-02-25 10:15:11,196 main DEBUG (org.apache.ibatis.transaction.jdbc.JdbcTransaction) - Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@157aa53]
2016-02-25 10:15:11,197 main DEBUG (org.apache.ibatis.datasource.pooled.PooledDataSource) - Returned connection 22522451 to pool.
就会发现cache命中,只执行了一次sql语句
------------------------------
如果二级缓存想要命中实现,则必须要将上一次sqlSession commit之后才能生效,不然将不会命中,原因:
两个不同的session必须提交前面一个session才能缓存生效的原因是因为mybatis的缓存会被一个transactioncache类包装住,所有的cache.putObject全部都会被暂时存到一个map里,等事务提交以后,这个map里的缓存对象才会被真正的cache类执行putObject操作。
这么设计的原因是为了防止事务执行过程中出异常导致回滚,如果get到object后直接put进缓存,万一发生回滚,就很容易导致mybatis缓存被脏读
mybatis的缓存机制是怎么样的?相关推荐
- MyBatis的缓存机制详解
MyBatis的缓存机制详解 MyBatis 包含一个非常强大的查询缓存特性,它可以非常方便地配置和定制,缓存可以极大的提升查询效率.MyBatis中默认定义了两级缓存,分别是一级缓存和二级缓存. ( ...
- MyBatis:缓存机制详解
本篇内容包括:MyBatis 缓存机制概述.一级缓存与二级缓存的介绍.配置和具体流程. 一.MyBatis 缓存机制概述 在我们常见的 OLTP(on-line transaction process ...
- Hibernate和MyBatis的缓存机制和比较
原文地址:https://my.oschina.NET/u/1445731/blog/416200?p=%7B%7BtotalPage%7D%7D Mybatis缓存 分为1级缓存和2级缓存,2级缓存 ...
- MyBatis之缓存机制
缓存即为存在内存中的临时数据.将用户经常查询的数据存放在缓存(内存)中,用户去查询数据就不用去每次去数据库中查询,而是去缓存中查询,从而提高了查询的效率,解决了高并发系统的性能问题.MyBatis提供 ...
- 11【MyBatis的缓存机制】
文章目录 二.Mybatis缓存机制 2.1 缓存介绍 2.2 一级缓存 2.2.1 一级缓存相关参数 2.2.2 一级缓存测试 2.2.3 一级缓存清空 2.2.3.1 设置localCacheSc ...
- (十二)Mybatis的缓存机制
文章目录 环境 Mybatis的缓存 一级缓存 一级缓存失效 方式一 方式二 二级缓存 MyBatis集成EhCache缓存 Mybatis学习目录 上一篇:(十一)MyBatis的高级映射及延迟加载 ...
- mybatis的缓存机制(一级缓存二级缓存和刷新缓存)和mybatis整合ehcache
1 查询缓存 1.1 什么是查询缓存 mybatis提供查询缓存,用于减轻数据压力,提高数据库性能. mybaits提供一级缓存,和二级缓存. 一级缓存是SqlSession级别的缓存.在 ...
- 框架:mybatis的缓存机制
一级缓存是SqlSession级别的缓存.在操作数据库时需要构造 sqlSession对象,在对象中有一个(内存区域)数据结构(HashMap)用于存储缓存数据.不同的sqlSession之间的缓存数 ...
- Mybatis的缓存机制Cache
Mybatis提供对缓存的支持,分为一级缓存和二级缓存,在没有配置的情况下,系统默认会使用一级缓存. 一级缓存(SqlSession级别) 我们都知道每个SqlSession对象之间的缓存是互不影响的 ...
最新文章
- 第四周实践项目7 多项式求和
- 微软一顿操作猛如虎,PowerShell 排名直线上升
- mysql数据加百分号_使用MySQL SELECT语句时,在每个值的末尾添加一个百分号(%)...
- Linux中g++与gcc的区别
- 计算机老师任课教师寄语,任课老师寄语大全
- 每日一题 2020.05.12
- 产生随机小数_如果取到小数区间内的任一数字?
- 如何写_家长如何为老师写评语
- Docker入坑指南之EXEC
- ERROR: libx264 not found
- 测评两款升压稳压芯片
- 哪种程序员最挣钱?平均月薪30.8K,网友说这是掌握世界的技术
- Codeforces 1379B.Dubious Cyrpto
- 12年时记录的一堆杂事
- kubernetes中metrics-server与HPA
- ASP.Net中常见的文件类型
- 【ORA-00257:archiver error. Connect internal only, until freed;清理归档日志】
- 首页滑滑滑,支付宝穿越回年轻样子
- 这几年已经组织开发或者即将开发我的或与我有关的第7个薪资管理系统、第5个人事管理系统,从中你觉得啥才真正值钱?...
- Mysql 知行必会 “子查询”
热门文章
- mat 内存分析 Linux,JVM内存分析工具MAT使用简介
- oracle 8i漏洞渗透,一次通过Oracle8i入侵系统之旅(组图)
- 设无向图g如图所示_阿里重磅发布大规模图神经网络平台 AliGraph,架构算法解读...
- 云桌面部署_东胜区检察院检察工作网统一业务系统2.0云桌面终端全面部署完成...
- ssd训练自己数据集
- 数据结构-队列1-顺序存储
- linux如何安装python环境变量中,Windows和linux环境下python安装及环境变量的配置
- 交流充电桩电路图_直流充电桩和交流充电桩给电动汽车充电过程中是如何工作的?...
- ❤️震惊!人生苦短,我用python来玩田忌赛马❤️
- 如何获取codeforces的完整数据