mybatis复习与总结(八)——缓存

一级缓存

1.一级缓存的作用域是SqlSession范围内的,mybatis默认开启一级缓存,无需任何配置。
2.当在同一个SqlSession中执行多次相同的sql语句,第一次执行完毕会将查询的数据写到缓存中,之后的查询直接从缓存中获取数据,不用去底层数据库查询。
3.如果SqlSession执行了DML操作(insert、update和delete),并提交到数据库,则一级缓存会被清空,以保证缓存中的数据是最新的。

二级缓存

1.二级缓存是mapper级别的缓存(mapper.xml的同一个namespace),可以被多个SqlSession共享。
2.开启二级缓存只需要在相应的xxxMapper.xml加入cache标签即可(因为二级缓存的总开关默认是开启的,我们就可以不再配置了)
3.二级缓存可自定义,实现了Cache接口的类都可以作为二级缓存,所以我们可以使用redis等第三方缓存数据库
4.自定义二级缓存(redis为例):
	实现Cache接口,重写相应的方法,在相应的mapper文件中加入
	<cache type="com.ywj.cache.MybatisRedisCache"></cache> type的值为具体的全类名
	注意事项:
		1.	在MyBatis中标签中有flushCache、useCache这两个配置属性
			如果属性是在select标签中设置: 
				flushCache默认为false,表示任何时候此标签中的sql语句被调用,都不会去清空本地缓存和二级缓存。 
				useCache默认为true,表示会将本条语句的查询结果进行二级缓存。 
			如果属性是在insert、update、delete标签中设置
				flushCache默认为true,表示任何时候语句被调用,都会导致本地缓存和二级缓存被清空。 
				useCache属性在该情况下不存在。
		2.	关于是否禁用懒加载,这里测试了不关闭懒加载也没有问题
			<settings>
				<!-- 禁用懒加载 --> 
				<setting name="lazyLoadingEnabled" value="false" />  
			</settings>
		3.要想使二级缓存生效,查询语句后需要用SqlSession对象需要调用commit()close()【这里当时踩坑了..不提交的话,缓存就没有写入】
			进行select操作后,调用SqlSession.close()方法,会将其一级缓存的数据放进二级缓存中,此时一级缓存随着SqlSession的关闭也就不存在了。
			进行select操作后,调用SqlSession.commit()方法,会将其一级缓存的数据放进二级缓存中,并清空一级缓存。
5.cache标签属性详解:
	1.flushInterval:刷新间隔,刷新缓存即清空缓存。默认没有刷新间隔,当执行增删改时刷新缓存。
	2.size:缓存数目,就是最多缓存地对象数。默认值1024
	3.readOnly:只读,默认false
	4.eviction:收回策略。默认LRU,有如下几种:
		1.LRU:最近最少使用的策略,移除最长时间不被使用的对象。
		2.FIFO:先进先出策略,按对象进入缓存的顺序来移除它们。
		3.SOFT:软引用策略,移除基于垃圾回收器状态和软引用规则的对象。
		4.WEAK:弱引用策略,更积极地移除基于垃圾回收器状态和软引用规则的对象。
	5.type:使用自定义缓存,默认使用mybatis内置地二级缓存

自定义二级缓存

public class MybatisRedisCache implements Cache{

		private String id;
		
		public MybatisRedisCache(String id) {
			this.id = id;
		}
		
		/**
		 * 清空缓存
		 */
		@Override
		public void clear() {
			JedisUtils.clear();
		}
		
		/**
		 * 获取缓存对象的唯一标识
		 */
		@Override
		public String getId() {
			return this.id;
		}
		
		/**
		 * 从缓存对象中获取key对应的value
		 */
		@Override
		public Object getObject(Object key) {
			return JedisUtils.get(key);
		}
		
		/**
		 * 获取读写锁
		 * 可选的方法,从3.2.6起这个方法不再被框架核心调用
		 * 任何需要的锁,都必须由缓存供应商提供
		 */
		@Override
		public ReadWriteLock getReadWriteLock() {
			return null;
		}
		
		/**
		 * 获取缓存对象中存储的键/值对的数量
		 * 可选的方法,没有被框架核心调用
		 */
		@Override
		public int getSize() {
			return JedisUtils.getSize();
		}
		
		/**
		 * 保存key/value到缓存对象中
		 * key可以是任何对象
		 */
		@Override
		public void putObject(Object key, Object value) {
			JedisUtils.set(key, value);
		}
		
		/**
		 * 可选的方法,没有被核心框架调用,移除key对应的value
		 */
		@Override
		public Object removeObject(Object key) {
			return null;
		}
		
		/**
		 * 重写equals方法
		 */
		@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());
		}
		
		/**
		 * 重写hashCode方法
		 */
		@Override
		public int hashCode() {
			if (getId() == null)
				throw new CacheException("Cache instances require an ID.");
			return getId().hashCode();
		}
	}

你可能感兴趣的:(Mybatis,mybatis)