java - mybatis - 缓存
mybatis有2级缓存
一级缓存(本地缓存, sqlsession级别)
二级缓存(全局缓存)
缓存时会把查询结果暂时存入内存,下次调用时直接返回结果,不再访问数据库。
. 一级缓存失效的情况:
1. 两次数据库会话 (不同的数据库回话会有各自独立的缓存空间)
2. 同一个sql,不同的参数(等于之前没有查到过,自然也就不会用到缓存)。
3. 有增删改的操作(更改过数据后会清空缓存,不管改的是哪个表的哪条数据) (读写分离的原因)
4. 手动清空缓存
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); SqlSession openSession = sqlSessionFactory.openSession(); openSession.clearCache();
一级缓存的实现原理:
有一个Cache接口,里面有一个map用来存放缓存数据。
底层继承Cache后用cache.put(key, value) 存入缓存。
key = 方法hashcode码,版本号,方法路径,会话编号,sql语句, 运行环境等拼成的一个字符串。 会话,sql,参数,版本号(数据更新时改变)等,有一个修改了,key都会变,进而导致缓存失效。
value = 查询结果。
每次访问数据库前会先查找缓存,如果没有相同的key再去访问数据库,并把结果存入map。 否则就直接从map中返回数据
二级缓存:
每次会话关闭时,会把一级缓存的数据存入二级缓存
每次查询时会先查2级缓存,再查1级缓存,所以不会出现1级和2级缓存中有相同数据的情况。
如果A 和 B 开始查询同一个数据, 分别存入了他们的一级缓存,当他们关闭时,后关闭的会把先关闭的存入2级缓存的数据覆盖。
二级缓存需要配置xml来决定用什么策略对哪个Dao添加2级缓存。
mybatis的配置文件:
添加:
<!--开启二级缓存--> <settings> <setting name="cacheEnabled" value="true"></setting> </settings>
<?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"></setting> </settings> <environments default="mysql"> <environment id="mysql"> <transactionManager type="JDBC"></transactionManager> <dataSource type="pooled"> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/mybatis_test"/> <!--mysql的库--> <property name="username" value="root"/> <!--mysql的账户密码,根据自己的mysql实际情况修改--> <property name="password" value="Zy1990526"/> </dataSource> </environment> </environments> <mappers> <mapper resource="UserinfoDao.xml"/> <!--扫描xml, 生成dao接口的实现类用来对数据进行操作--> </mappers> </configuration>
目标Dao的配置文件
添加
<cache></cache>
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.dao.UserinfoDao"> <!--对象接口的全类名--> <cache eviction="LRO"></cache> <!--表示这个dao使用二级缓存--> <!-- 可用参数: eviction: 缓存策略 1. LRU: 移除最长时间没有被使用的数据 2. FIFO: 移除最先进入缓存的数据 3. SOFI: 基于垃圾回收器状态和软引用规则 4. WEAK: 基于垃圾回收期状态和弱引用规则 flushInterval 刷新间隔 默认不设置,不设置时每次调用sql语句时刷新 size 可以储存的最大缓存对象数量 readOnly true: 只读缓存, 不能覆盖,所有查询者返回相同的缓存数据,不能修改。 返回的是缓存引用,别人修改数据后,可能会导致两次相同的语句查到的结果不同。 false: 返回缓存对象的拷贝, 保证安全。 默认是false --> <select id="getUserById" parameterType="int" resultType="com.entities.Userinfo"> <!--id是方法名, resulttype是返回类型--> select * from userinfo where user_id = #{user_id} <!--sql语句,参数用 #{方法的参数名} 表示--> </select> </mapper>