使用Redis做Mybatis二级缓存

1. 介绍

使用mybatis时可以使用二级缓存提高查询速度,进而改善用户体验。

使用redis做mybatis的二级缓存可是内存可控<如将单独的服务器部署出来用于二级缓存>,管理方便。

2. 相关Jar包

2.1).jedis-2.9.0.jar  
2.2).spring-data-commons-1.13.7.RELEASE.jar
2.3).spring-data-keyvalue-1.2.7.RELEASE.jar

2.4).spring-data-redis-1.8.7.RELEASE.jar

3. 实现思路

3.1). 配置redis.xml 设置redis服务连接各参数;
3.2). 在配置文件中使用 标签,设置开启二级缓存;
3.3). 在mapper.xml 中使用 将cache映射到指定的RedisCacheClass类中;
3.4).映射类RedisCacheClass 实现 MyBatis包中的Cache类,并重写其中各方法;

    在重写各方法体中,使用redisFactory和redis服务建立连接,将缓存的数据加载到指定的redis内存中(putObject方法)或将redis服务中的数据从缓存中读取出来(getObject方法);

    在redis服务中写入和加载数据时需要借用spring-data-redis.jar中JdkSerializationRedisSerializer.class中的序列化(serialize)和反序列化方法(deserialize),此为包中封装的redis默认的序列化方法;

3.5).映射类中的各方法重写完成后即可实现mybatis数据二级缓存到redis服务中;

4. 代码实践

4.1).在springmvc.xml 中配置redis相关配置、或者直接写redis.xml


    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:task="http://www.springframework.org/schema/task"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/mvc
    http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
    http://www.springframework.org/schema/tx 
    http://www.springframework.org/schema/tx/spring-tx.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-3.0.xsd
    http://www.springframework.org/schema/task

    http://www.springframework.org/schema/task/spring-task-3.0.xsd" >

   
     
       
    
    
   
   
   
   
   
       
           
                classpath:sysconfig/jdbc.properties
                classpath:sysconfig/redis.properties
           

       

     

     
             p:driverClassName="${jdbc.driverClassName}"
        p:url="${jdbc.databaseurl}"
        p:username="${jdbc.username}"
        p:password="${jdbc.password}" >
       
            ${jdbc.maxActive}
       
  
       
            ${jdbc.initialSize}
       
  
       
            ${jdbc.maxWait}
       
  
       
            ${jdbc.maxIdle}
       

       
            ${jdbc.minIdle}
       

       
       
            18000000
       

       
            10800000
       

       
            SELECT 1
       

       
            true
       

   

    
   
   
       
       
         
       
   

        
   
   
       
       
   

    
        
   
      
          
          
          
          
   

    
   
 
       
       
       
       
       
   
      
   
   
       
   
      
    
              

 

4.2 mybatis.xml 配置开启二级缓存

  
      PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
     "http://mybatis.org/dtd/mybatis-3-config.dtd">

   
   
       

       

       

       

       
       

       
       
   
   

4.3 在mapper.xml中映射缓存类RedisCacheClass


"http://mybatis.org/dtd/mybatis-3-mapper.dtd">






    insert into person(
        login_id,
        user_name,
        gender,
        birthday,
        remark
    )values(
        #{login_id},
        #{user_name},
        #{gender},
        #{birthday},
        #{remark}
    )

4.4 实现Mybatis中的Cache接口

  Cache.class源码:

/*
 *  Copyright 2009-2012 the original author or authors.
 *  http://www.apache.org/licenses/LICENSE-2.0*/
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();

}

RedisCache.java

package demo.redis.cache;

import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import org.apache.ibatis.cache.Cache;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.connection.jedis.JedisConnection;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;
import redis.clients.jedis.exceptions.JedisConnectionException;

public class RedisCache implements Cache //实现类
{
    private static final Logger logger = LoggerFactory.getLogger(RedisCache.class);

    private static JedisConnectionFactory jedisConnectionFactory;

    private final String id;

    /**
     * The {@code ReadWriteLock}.
     */
    private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();


    public RedisCache(final String id) {
        if (id == null) {
            throw new IllegalArgumentException("Cache instances require an ID");
        }
        logger.debug("MybatisRedisCache:id=" + id);
        this.id = id;
    }

    @Override
    public void clear()
    {
        JedisConnection connection = null;
        try
        {
            connection = jedisConnectionFactory.getConnection(); //连接清除数据
            connection.flushDb();
            connection.flushAll();
        }
        catch (JedisConnectionException e)
        {
            e.printStackTrace();
        }
        finally
        {
            if (connection != null) {
                connection.close();
            }
        }
    }

    @Override
    public String getId()
    {
        return this.id;
    }

    @Override
    public Object getObject(Object key)
    {
        Object result = null;
        JedisConnection connection = null;
        try
        {
            connection = jedisConnectionFactory.getConnection();
            RedisSerializer serializer = new JdkSerializationRedisSerializer(); //借用spring_data_redis.jar中的JdkSerializationRedisSerializer.class
            result = serializer.deserialize(connection.get(serializer.serialize(key))); //利用其反序列化方法获取值
        }
        catch (JedisConnectionException e)
        {
            e.printStackTrace();
        }
        finally
        {
            if (connection != null) {
                connection.close();
            }
        }
        return result;
    }

    @Override
    public ReadWriteLock getReadWriteLock()
    {
        return this.readWriteLock;
    }

    @Override
    public int getSize()
    {
        int result = 0;
        JedisConnection connection = null;
        try
        {
            connection = jedisConnectionFactory.getConnection();
            result = Integer.valueOf(connection.dbSize().toString());
        }
        catch (JedisConnectionException e)
        {
            e.printStackTrace();
        }
        finally
        {
            if (connection != null) {
                connection.close();
            }
        }
        return result;
    }

    @Override
    public void putObject(Object key, Object value)
    {
        JedisConnection connection = null;
        try
        {
            logger.info(">>>>>>>>>>>>>>>>>>>>>>>>putObject:"+key+"="+value);
            connection = jedisConnectionFactory.getConnection();
            RedisSerializer serializer = new JdkSerializationRedisSerializer(); //借用spring_data_redis.jar中的JdkSerializationRedisSerializer.class
            connection.set(serializer.serialize(key), serializer.serialize(value)); //利用其序列化方法将数据写入redis服务的缓存中
            
        }
        catch (JedisConnectionException e)
        {
            e.printStackTrace();
        }
        finally
        {
            if (connection != null) {
                connection.close();
            }
        }
    }

    @Override
    public Object removeObject(Object key)
    {
        JedisConnection connection = null
        Object result = null;
        try
        {
            connection = jedisConnectionFactory.getConnection();
            RedisSerializer serializer = new JdkSerializationRedisSerializer();
            result =connection.expire(serializer.serialize(key), 0);
        }
        catch (JedisConnectionException e)
        {
            e.printStackTrace();
        }
        finally
        {
            if (connection != null) {
                connection.close();
            }
        }
        return result;
    }

    public static void setJedisConnectionFactory(JedisConnectionFactory jedisConnectionFactory) {
        RedisCache.jedisConnectionFactory = jedisConnectionFactory;
    }

}



你可能感兴趣的:(mybatis)