mybatis–基础–3.7–xml映射文件–缓存
代码地址
https://gitee.com/DanShenGuiZu/learnDemo/tree/mysql_mybaties_DB/mybatis-learn-master
1、介绍
- 默认:没有开启缓存的,除了局部的session缓存,可以增强变现而且处理循环依赖也是必须的。
1.1、开启二级缓存
你需要在你的SQL映射文件中添加一行
<cache/>
1.2、功能
- 映射语句文件中的所有select语句将会被缓存。
- 映射语句文件中的所有insert,update和delete语句会刷新缓存。
- 缓存会使用LeastRecentlyUsed(LRU,最近最少使用的)算法来收回。
- 缓存存储对象的1024个引用。
- 缓存会被视为是read/write(可读/可写)的缓存,意味着对象检索不是共享的,而且可以安全地被调用者修改,而不干扰其他调用者或线程所做的潜在修改。
1.3、属性
<cache
eviction="FIFO"
flushInterval="60000"
size="512"
readOnly="true"/>
- 创建了一个 FIFO 缓存,并每隔 60 秒刷新,存数结果对象512个引用,而且返回的对象被认为是只读的,因此在不同线程中的调用者之间修改它们会导致冲突。
- eviction:回收策略
- LRU:最近最少使用的
- 移除最长时间不被使用的对象。
- 默认:LRU
- FIFO:先进先出
- 按对象进入缓存的顺序来移除它们。
- SOFT:软引用
- 移除基于垃圾回收器状态和软引用规则的对象。
- WEAK:弱引用
- 更积极地移除基于垃圾收集器状态和弱引用规则的对象。
- LRU:最近最少使用的
- flushInterval:刷新间隔
- 默认:不设置,没有刷新间隔,没有过期时间,缓存仅仅调用语句时刷新。
- size
- 可以缓存对象引用的数目
- 默认值:1024。
- readOnly(只读)
- true:
- 只读缓存
- 给所有调用者返回缓存对象的相同实例,因此这些对象不能被修改。这提供了很重要的性能优势。
- false:
- 读写缓存
- 返回缓存对象的拷贝(通过序列化)。这会慢一些,但是安全
- 默认:false。
- true:
2、Cache接口
2.1、Cache接口
package org.apache.ibatis.cache;
public interface Cache {
String getId();
void putObject(Object key, Object value);
Object getObject(Object key);
Object removeObject(Object key);
void clear();
int getSize();
default ReadWriteLock getReadWriteLock() {
return null;
}
}
2.2、Cache接口默认实现类
public class PerpetualCache implements Cache {
private final String id;
private final Map<Object, Object> cache = new HashMap<>();
public PerpetualCache(String id) {
this.id = id;
}
@Override
public String getId() {
return id;
}
@Override
public int getSize() {
return cache.size();
}
@Override
public void putObject(Object key, Object value) {
cache.put(key, value);
}
@Override
public Object getObject(Object key) {
return cache.get(key);
}
@Override
public Object removeObject(Object key) {
return cache.remove(key);
}
@Override
public void clear() {
cache.clear();
}
@Override
public boolean equals(Object o) {
if (getId() == null) {
throw new CacheException("Cache instances require an ID.");
}
if (this == o) {
return true;
}
if (!(o instanceof Cache)) {
return false;
}
Cache otherCache = (Cache) o;
return getId().equals(otherCache.getId());
}
@Override
public int hashCode() {
if (getId() == null) {
throw new CacheException("Cache instances require an ID.");
}
return getId().hashCode();
}
}
3、自定义缓存–在mapper.xml文件中配置
- mybatis的一级缓存和二级缓存都实现了cache接口,要实现自定义缓存而不使用mybatis默认的缓存,那么就要自己实现cache接口,并在mapper.xml文件中指明缓存的类型。
3.1、代码
结构
核心代码
全部代码
@Data
public class User {
private Long id;
private String userName;
private String password;
}
public interface UserMapper {
User selectById(Integer id);
}
UserMapper.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.cl.mybatis.learn.day19.dao.UserMapper">
<!--开启自定义缓存-->
<cache type="com.cl.mybatis.learn.day19.MyCache"></cache>
<select id="selectById" resultType="user">
select * from user where id = #{id}
</select>
</mapper>
public class Mybatis001 {
public static void main(String[] args) throws Exception {
String resource = "common1/mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession session = sqlSessionFactory.openSession();
UserMapper userMapper = session.getMapper(UserMapper.class);
try {
User user = userMapper.selectById(1);
System.out.println("user:" + user.toString());
System.out.println("-----换行-------");
System.out.println();
System.out.println();
User user1 = userMapper.selectById(1);
System.out.println("user1:" + user1.toString());
} finally {
session.close();
}
}
}
public class MyCache extends PerpetualCache implements Cache {
public MyCache(String id) {
super(id);
System.out.println("构建MyCache");
}
@Override
public void putObject(Object key, Object value) {
System.out.println("key的值为: " + key);
System.out.println("value的值为: " + value);
super.putObject(key, value);
}
@Override
public Object getObject(Object key) {
return super.getObject(key);
}
}
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.cl.mybatis.learn.day19.bean"/>
</typeAliases>
<environments default="development1">
<environment id="development1">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://zhoufei.ali.db.com:3306/test"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<mappers>
<package name="com.cl.mybatis.learn.day19.dao"/>
</mappers>
</configuration>
3.2、结果
构建MyCache
Cache Hit Ratio [com.cl.mybatis.learn.day19.dao.UserMapper]: 0.0
Opening JDBC Connection
Created connection 1791868405.
Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@6acdbdf5]
==> Preparing: select * from user where id = ?
==> Parameters: 1(Integer)
<== Columns: id, user_name, password
<== Row: 1, user, $2a$10$82imG0H/aJzplJsDlOsjheLRN60AGS.hH7E4kNRB/cQmgbbvD6ig6
<== Total: 1
user:User(id=1, userName=null, password=$2a$10$82imG0H/aJzplJsDlOsjheLRN60AGS.hH7E4kNRB/cQmgbbvD6ig6)
-----换行-------
Cache Hit Ratio [com.cl.mybatis.learn.day19.dao.UserMapper]: 0.0
user1:User(id=1, userName=null, password=$2a$10$82imG0H/aJzplJsDlOsjheLRN60AGS.hH7E4kNRB/cQmgbbvD6ig6)
key的值为: -1547677612:3108298604:com.cl.mybatis.learn.day19.dao.UserMapper.selectById:0:2147483647:select * from user where id = ?:1:development1
value的值为: [User(id=1, userName=null, password=$2a$10$82imG0H/aJzplJsDlOsjheLRN60AGS.hH7E4kNRB/cQmgbbvD6ig6)]
Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@6acdbdf5]
Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@6acdbdf5]
Returned connection 1791868405 to pool.
4、自定义缓存–使用注解
xml映射文件去掉
<cache type="com.cl.mybatis.learn.day19.MyCache"></cache>
在接口上添加注解
@CacheNamespace(implementation= MyCache.class,eviction= MyCache.class)
public interface UserMapper {
User selectById(Integer id);
}
5、查询select中的缓存
<!--useCache对一级缓存没有影响,设置为false会影响二级缓存-->
<!--flushCache默认为false,不清空缓存,如果改为true每次查询之前都会清空缓存-->
<select useCache="true" id="selectById" resultType="user">
select * from user where id = #{id}
</select>
- useCache:
- 对一级缓存没有影响,设置为false会影响二级缓存
- flushCache
- false,不清空缓存,默认
- true:每次查询之前都会清空缓存
6、参照缓存
<cache-ref namespace="com.someone.application.data.SomeMapper"/>
- cache-ref:引用另外一个缓存
- 当前xml映射文件中,引用