(十一)mybatis之整合ehcache缓存
一、二级缓存
大家都知道使用mybatis就要先获取sqlsessionfactory,继而使用sqlsession来和数据库交互,每次只需要使用sqlsession对象提供的方法就好,当我们需要第一次查询一条记录时,会直接从数据库中获取记录,但是当我们第二次还使用相同的条件查询时,如果还从数据库中查询,这势必是不合理的,如果数据量大的话,会给数据库造成很大的压力,所以开发框架的作者,也考虑到了这点,所以在sqlsession中有了优化,他会自动缓存查询条件,注意是查询条件,如果多次查询条件一致,才会从缓存中提取,否则就会从数据库中查询,还用就是如果调用了commit(update,insert,delete)操作就会清空一级缓存和二级缓存,二级缓存 就是多个sqlsession共享的缓存空间,需要注意的是和hibernate 不一样,mybatis的二级缓存是以命名空间划分的,即每一个namespace都会有一个二级缓存,也就是说同一个sql空间下的操作才会共享二级缓存否则不共享,由于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包:
三、配置
- 首先在全局配置中加入设置,虽然默认就是打开的,但是这样是为了告诉别人你使用了第三方缓存:
- 在mybatis总配置文件中配置:
<setting name="cacheEnabled" value="true"/>
- 在mybatis总配置文件中配置:
-
在mapper.xml中加入缓存实现类,指定缓存的实现类配置:
<cache type="org.mybatis.caches.ehcache.EhcacheCache"/>
-
加入缓存的具体配置,命名为ehcache.xml就可不用管了,如果指定缓存到磁盘上,还需要po实现java类序列化接口,Serializable
-
ehcache.xml
:
<?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>
四、测试
/** * 测试二级缓存,Student开启了二级缓存 */ @Test public void testSecondCache(){ //获取session SqlSession session1=SqlUtils.getSession(); SqlSession session2=SqlUtils.getSession(); SqlSession session3=SqlUtils.getSession(); System.out.println(session1.selectOne("Student.selectStudent",1)); System.out.println(session2.selectOne("Student.selectStudent",1)); System.out.println(session3.selectOne("Student.selectStudent",1)); } }
五、注意
如果控制台报错,如下:
SLF4J: Failed to load class “org.slf4j.impl.StaticLoggerBinder”.
- 原来这是因为sl4j和log4j的不兼容导致的,具体处理方案如下:
首先看看你工程中的sl4j-api的版本(比如我的是1.5.11),然后在http://mvnrepository.com/搜索slf4j-log4j12,会出现SLF4J LOG4J 12 Binding,点击进入,会有很多版本的 slf4j-log4j12,我们点击1.5.11版本的slf4j-log4j12进入详细信息页面,查看依赖的log4j,这个版本的slf4j-log4j12依赖的是1.2.14版本的log4j。
所以,我们在我们的工程中添加1.5.11版本的slf4j-log4j12和1.2.14版本的log4j,问题完美解决。
- 如果是maven工程,则依赖的<scope>test</scope>可能是test,根据需要修改为compile或者其他。