mybatis 与 ehcache 整合

1.简介
MyBatis 是支持普通SQL 查询,存储过程和高级映射的优秀持久层框架。MyBatis 消除了几乎所有的JDBC 代码和参数的手工设置以及结果集的检索。
Ehcache 是现在最流行的纯Java开源缓存框架,配置简单、结构清晰、功能强大,最初知道它,是从Hibernate的缓存开始的。
2. 准备工作
下载mybatis相关包与ehcache相关包
ehcache-core-2.4.4.jar
mybatis-ehcache-1.0.0.jar
slf4j-api-1.6.1.jar
slf4j-log4j12-1.6.2.jar
3. 配置步骤:
用hsqldb作为数据库,使用mybatis自定义缓存。
数据库建表语句:
create table category (
    catid varchar(10) not null,
    name varchar(80) null,
    descn varchar(255) null,
    constraint pk_category primary key (catid)
);
create table product (
    productid varchar(10) not null,
    category varchar(10) not null,
    name varchar(80) null,
    descn varchar(255) null,
    constraint pk_product primary key (productid),
        constraint fk_product_1 foreign key (category)
        references category (catid)
);
create index productCat on product (category);
create index productName on product (name); 
insert数据的语句:
INSERT INTO category VALUES ('FISH','Fish','<image src="../images/fish_icon.gif"><font size="5" color="blue"> Fish</font>');
INSERT INTO category VALUES ('DOGS','Dogs','<image src="../images/dogs_icon.gif"><font size="5" color="blue"> Dogs</font>');
INSERT INTO product VALUES ('FI-SW-01','FISH','Angelfish','<image src="../images/fish1.gif">Salt Water fish from Australia');
INSERT INTO product VALUES ('FI-SW-02','FISH','Tiger Shark','<image src="../images/fish4.gif">Salt Water fish from Australia');
4. cache配置步骤:
(1).在classpath下配置ehcache.xml。这个是ehcache的默认配置文件。
<?xml version="1.0" encoding="UTF-8"?>  
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
    xsi:noNamespaceSchemaLocation="../bin/ehcache.xsd">  
    <defaultCache overflowToDisk="true" eternal="false" maxElementsInMemory="1"/>  
    <diskStore path="D:/cache" />  
</ehcache>  
(2).在需要的Mapper.xml中配置cache。
上面的配置是全局的cache,在Mapper.xml中可以根据自己的需要,对这个Mapper中进行cache的配置,可以配置某一条sql语句不进行cache。
<cache type="org.mybatis.caches.ehcache.LoggingEhcache"/> //最普通的设置,沿用全局设置
<cache type="org.mybatis.caches.ehcache.LoggingEhcache" > 
    <property name="timeToIdleSeconds" value="3600"/><!--1 hour-->
    <property name="timeToLiveSeconds" value="3600"/><!--1 hour-->
    <property name="maxEntriesLocalHeap" value="1000"/>
    <property name="maxEntriesLocalDisk" value="10000000"/>
    <property name="memoryStoreEvictionPolicy" value="LRU"/>
<cache>
<!--
配置这个mapper使用LRU替换策略。
(个人比较赞同这种配置,因为每个表的数据都不一样,有一些需要经常更新,有得可能某几个字段需要经常做连接,
使用一样的cache不太合适)
--> 
mybatis默认是启用cache的,所以对于某一条不想被cache的sql需要把useCache="false"
<select id="getCategory" parameterType="string" resultType="Category" useCache="false">
5. 测试:
    private ApplicationContext application;
    private CategoryMapper categoryMapper;
    private ProductMapper productMapper;
    private String[] categoryId = { "FISH", "DOGS", "REPTILES", "CATS", "BIRDS" };
    @Before
    public void initSpring() {
        application = new FileSystemXmlApplicationContext(
                "resource/applicationContext.xml");
        categoryMapper = application.getBean(CategoryMapper.class);
        productMapper = application.getBean(ProductMapper.class);
    }
    @Test
    public void testSelect() {
        // the first time
        long begin = System.nanoTime();
        categoryMapper.getCategory(categoryId[0]);
        long end = System.nanoTime() - begin;
        print("count :" + end);
        // the second time
        begin = System.nanoTime();
        categoryMapper.getCategory(categoryId[0]);
        end = System.nanoTime() - begin;
        print("count :" + end);
        // the third time
        begin = System.nanoTime();
        categoryMapper.getCategory(categoryId[0]);
        end = System.nanoTime() - begin;
        print("count :" + end);
        //
    }
    @Test
    public void testInsert() {
        // the second time
        long begin = System.nanoTime();
        //
        Product p1 = productMapper.getProduct("FI-SW-01");
        long end = System.nanoTime() - begin;
        print("count :" + end);
        print("Category :"+p1.getCategoryId());
        Map<String, String> parame = new HashMap<String, String>();
        parame.put("categoryId", "DOGS");
        parame.put("productId", "FI-SW-01");
        
        begin = System.nanoTime();
        productMapper.updateProductById(parame);
        end = System.nanoTime() - begin;
        print("count :"+end);
        begin = System.nanoTime();
        Product p2 = productMapper.getProduct("FI-SW-01");
        end = System.nanoTime() - begin;
        print("count :"+end);
        print("Category :"+p2.getCategoryId());
        
    } 
运行的结果
log4j debug开启:
16 09:42:16,447 org.apache.ibatis.logging.slf4j.Slf4jImpl: Cache Hit Ratio [org.mybatis.jpetstore.persistence.CategoryMapper]: 0.0
DEBUG 2013-05-16 09:42:16,501 org.apache.ibatis.logging.slf4j.Slf4jImpl: ==> Executing: SELECT CATID AS categoryId, NAME, DESCN AS description FROM CATEGORY WHERE CATID = ?
DEBUG 2013-05-16 09:42:16,502 org.apache.ibatis.logging.slf4j.Slf4jImpl: ==> Parameters: FISH(String)
DEBUG 2013-05-16 09:42:16,542 org.apache.ibatis.logging.slf4j.Slf4jImpl: <== Columns: CATEGORYID, NAME, DESCRIPTION
DEBUG 2013-05-16 09:42:16,542 org.apache.ibatis.logging.slf4j.Slf4jImpl: <== Row: FISH, Fish, <image src="../images/fish_icon.gif"><font size="5" color="blue"> Fish</font>
count :204671120
Cache Hit Ratio [org.mybatis.jpetstore.persistence.CategoryMapper]: 0.5
count :3737320
Cache Hit Ratio [org.mybatis.jpetstore.persistence.CategoryMapper]: 0.6666666666666666
count :2349519
这里可以很清晰的看到,第一次取数据的时候,mybatis运行了sql语句,并且得到了返回的数据,因为是第一次,所以 Cache Hit Ratio 是0.0,当第二次的时候,因为cache已经存在查询的数据集,因此,mybatis没有发起查询,直接得到了数据。两次的时间差了100倍。
log4j INFO,关掉debug得到的查询速度快了一点
count :126226400
count :1803960
count :772080
inset:语句的运行。首先查一遍,让cache里面有数据,然后update里面的数据,再取出来。从所耗费的时间来看,update只是在cache进行了,只有等cache过期了,数据才会写入数据库。
count :121264080
Category :FISH
count :4028440
count :1509640
Category :DOGS
6.总结思考
查看了一下硬盘cache的文件夹,发现mybatis对于每个Mapper都有自己独立的cache文件,查看mybatis-ehcache的实现:
private static final CacheManager CACHE_MANAGER = CacheManager.create();
每一个Mapper都对应的有自己的CacheManager。
虽然,通过log可以看到cache hit radio 但是,我需要像ehcache整合到spring那样子可以获得每个由mybatis代理运行的cache对象。查看了很久的代码,发现里面的代理对象都是私有的,并不能被用户调用,所以现在还没有找到细粒化操作mybatis cache的方法。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值