mybatis和hibernate一样都是优秀的orm框架,但是两者的定位不同,所以有所差异,这里我们就从缓存的角度来介绍一下mybatis:
大家都知道使用mybatis就要先获取sqlsessionfactory,继而使用sqlsession来和数据库交互,每次只需要使用sqlsession对象提供的方法就好,当我们需要第一次查询一条记录时,会直接从数据库中获取记录,但是当我们第二次还使用相同的条件查询时,如果还从数据库中查询,这势必是不合理的,如果数据量大的话,会给数据库造成很大的压力,所以开发框架的作者,也考虑到了这点,所以在sqlsession中有了优化,他会自动缓存查询条件,注意是查询条件,如果多次查询条件一致,才会从缓存中提取,否则就会从数据库中查询,还用就是如果调用了commit(update,insert,delete)操作就会清空一级缓存和二级缓存,二级缓存 就是多个sqlsession共享的缓存空间,需要注意的是和hibernate 不一样,mybatis的二级缓存是以命名空间划分的,即每一个namespace都会有一个二级缓存,也就是说同一个sql空间下的操作才会共享二级缓存否则不共享,由于mybatis的一二级缓存都是更新时清空缓存,这也造成了,mybatis的弊端,如果缓存了大量一二级缓存,这时有一个更新操作,这些缓存都会清除,这是mybatis的弊端,但是这个机制虽然效率不高,但是避免了数据的脏读,保持了数据的一致性.
mybatis缓存图片详解
一级缓存的使用不需要我们配置,是mybatis自己实现的hashmap内存级别的缓存,我们没有配置的必要,我们只需要了解即可
二级缓存,由于mybatis自己实现的二级缓存不是很好,所以我们需要整合第三方缓存框架,来满足我们的需求,实现分布式缓存和中央缓存,
mybatis提供了一个二级缓存的接口允许所有第三方缓存框架实现这个接口就可以和mybatis对接上,
这个接口就是:
/*
* Copyright 2009-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.ibatis.cache;
import java.util.concurrent.locks.ReadWriteLock;
public interface Cache {
String getId();
int getSize();
void putObject(Object key, Object value);
Object getObject(Object key);
Object removeObject(Object key);
void clear();
ReadWriteLock getReadWriteLock();
}
mybatis的二级缓存默认就是开启的,mybatis的二级缓存默认实现类是:PerpetualCache,这个二级缓存也是一个内存级别的,所以建议大家不要使用
目前主流的二级缓存框架我就知道ehcache,但是我们要使用ehcache,需要两个jar包
一个是ehcache包和mybatis-ehcache包:
配置问题:
1:首先在全局配置中加入设置,虽然默认就是打开的,但是这样是为了告诉别人你使用了第三方缓存:
** <setting name="cacheEnabled" value="true"/>**
2:在mapper.xml中加入缓存实现类,指定缓存的实现类配置:
<cache type="org.mybatis.caches.ehcache.EhcacheCache"/>
3:**加入缓存的具体配置,命名为ehcache.xml就可不用管了,如果指定缓存到磁盘上,还需要po实现java类序列化接口,Serializable**:
<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd">
<diskStore path="F:\cache"/>
<defaultCache
maxElementsInMemory="3000"
eternal="false"
timeToIdleSeconds="3600"
timeToLiveSeconds="3600"
overflowToDisk="true"
diskPersistent="false"
diskExpiryThreadIntervalSeconds="100"
memoryStoreEvictionPolicy="LRU"
/>
<cache name="userCache"
maxElementsInMemory="3000"
eternal="false"
overflowToDisk="true"
timeToIdleSeconds="3600"
timeToLiveSeconds="3600"
memoryStoreEvictionPolicy="LFU"
/>
</ehcache>
测试代码:
/**
* session 不关闭,查询结果未进入缓存中
*/
@Test
public void testSecondCache(){
//获取session
SqlSession session1=getSession();
SqlSession session2=getSession();
SqlSession session3=getSession();
System.out.println(session1.selectOne("student.getById",1L));
System.out.println(session2.selectOne("student.getById",1L));
System.out.println(session3.selectOne("student.getById",1L));
}
/**
* session 关闭,查询结果进入缓存中
*/
@Test
public void testCache2() throws Exception{
//获取session
SqlSession session1=getSession();
SqlSession session2=getSession();
SqlSession session3=getSession();
System.out.println(session1.selectOne("student.getById",1L));
session1.close();
System.out.println(session2.selectOne("student.getById",1L));
session2.close();
System.out.println(session3.selectOne("student.getById",1L));
session3.close();
}
二级缓存效果图:
第一次测试,未关闭session可以看到缓存不生效,效果如下
第二次,每次查询完毕后,立即关闭session,缓存生效命中
第二次命中率 0.5第三次 命中率0.6666
磁盘缓存,java类序列化:
严重道歉:这篇博客是当年自己学艺不精所写,出现了一些错误,给后来学习的人造成了麻烦,不好意思
所以花了一些时间完善
不过目前mybatis的二级缓存一般不建议使用,可以使用spring提供的缓存注解实现业务层缓存即可