zl程序教程

您现在的位置是:首页 >  数据库

当前栏目

使用redis做mybaties的二级缓存(1)

Redis 二级缓存 使用
2023-09-11 14:13:55 时间
前言
 
1.环境: spring3.2.4+jedis2.7.2+redis服务3.0.7+mybaties3.2.4
 
 
 
正文
 
1.mybatis-config.xml开启二级缓存

 

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC  
    "-//mybatis.org//DTD Config 3.0//EN"  
    "http://mybatis.org/dtd/mybatis-3-config.dtd">  
<configuration>  
    <settings>
        <!-- 这个配置使全局的映射器启用或禁用缓存 -->
        <setting name="cacheEnabled" value="true" />
        <!-- 对于未知的SQL查询,允许返回不同的结果集以达到通用的效果 -->
        <setting name="multipleResultSetsEnabled" value="true" />
        <!-- 配置默认的执行器。SIMPLE 执行器没有什么特别之处。REUSE 执行器重用预处理语句。BATCH 执行器重用语句和批量更新 -->
        <setting name="defaultExecutorType" value="REUSE" />
        <!-- 全局启用或禁用延迟加载。当禁用时,所有关联对象都会即时加载。 -->
        <setting name="lazyLoadingEnabled" value="false" />
        <setting name="aggressiveLazyLoading" value="true" />
        <!-- <setting name="enhancementEnabled" value="true"/> -->
        <!-- 设置超时时间,它决定驱动等待一个数据库响应的时间。 -->
        <setting name="defaultStatementTimeout" value="25000" />
        
        <setting name="logImpl" value="STDOUT_LOGGING" />
    </settings>
    <mappers>  
        <mapper resource="lq/User.xml"/>  
        <mapper resource="lq/redis/cache/Role.xml"/> 
        <mapper resource="lq/redis/cache/Resc.xml"/> 
    </mappers>  
</configuration>

 

2.Resc.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"   
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">  
<mapper namespace="lq.redis.cache.RescMapper">  

    <!-- redis缓存 -->
     <cache eviction="LRU" type="lq.redis.cache.RedisCache" />  

<select id="getResc" parameterType="lq.redis.cache.Resc" resultType="lq.redis.cache.Resc" useCache="true">  
    SELECT id,NAME,res_type,res_string,priority,descn FROM resc WHERE id=#{id}
</select>  

<select id="getRescPageList" parameterType="lq.redis.cache.Resc" resultType="lq.redis.cache.Resc" useCache="true">  
    SELECT id,NAME,res_type,res_string,priority,descn FROM resc
</select>  

<select id="getRescPageCount" parameterType="lq.redis.cache.Resc" resultType="String"  useCache="true">  
    SELECT count(id) FROM resc 
</select> 

<insert id="addResc" parameterType="lq.redis.cache.Resc" flushCache="true">  
   INSERT INTO resc (id,NAME,res_type,res_string,priority,descn) VALUES (
   #{id},#{NAME},#{res_type},#{res_string},#{priority},#{descn}
   )  
</insert>  

<update id="updateResc" parameterType="lq.redis.cache.Resc" flushCache="true" >  
update resc set NAME= #{name}  where id=#{id}
</update> 

<delete id="delResc" parameterType="lq.redis.cache.Resc" flushCache="true">  
DELETE FROM resc WHERE id=#{id}
</delete> 

<select id="getRescAndRole" parameterType="lq.redis.cache.RescRole" resultType="lq.redis.cache.RescRole" useCache="true">  
SELECT resc.id,resc.NAME,resc.res_type,resc.res_string,resc.priority,resc.descn ,role.NAME AS roleName FROM resc
LEFT JOIN resc_role ON resc.id=resc_role.resc_id
LEFT JOIN role ON resc_role.role_id=role.id

</select> 
  
</mapper>

1.<cache>,
2.flushCache="true"
3.useCache="true"
4.getRescAndRole,多表查询最好别用缓存,理由 http://www.cnblogs.com/crazylqy/p/5983507.html

 

3.RedisCache

package lq.redis.cache;

import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

import lq.redis.IbatisRedisClient;
import lq.util.SpringUtil;

import org.apache.ibatis.cache.Cache;
import org.apache.ibatis.cache.CacheKey;
import org.apache.ibatis.logging.Log;
import org.apache.ibatis.logging.LogFactory;

import redis.clients.jedis.Jedis;
 
public class RedisCache implements Cache {
    private static Log logger = LogFactory.getLog(RedisCache.class);
    /** The ReadWriteLock. */
    private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
 
    private String id;
 
    public RedisCache(final String id) {
        if (id == null) {
            throw new IllegalArgumentException("Cache instances require an ID");
        }
        logger.debug(">>>>>>>>>>>>>>>>>>>>>>>>MybatisRedisCache:id=" + id);
        this.id = id;
    }
 
    public String getId() {
        return this.id;
    }
 
    public int getSize() {
        IbatisRedisClient ibatisRedisClientImpl=(IbatisRedisClient)SpringUtil.getObject("ibatisRedisClient"); 
        Jedis jedis = ibatisRedisClientImpl.getResource();
        try{                     
            return Integer.valueOf(jedis.dbSize().toString());
        }finally{
            ibatisRedisClientImpl.returnResource(jedis);
        }

    }
 
    public void putObject(Object key, Object value) {        
        IbatisRedisClient ibatisRedisClientImpl=(IbatisRedisClient)SpringUtil.getObject("ibatisRedisClient"); 
        Jedis jedis = ibatisRedisClientImpl.getResource();
        try{                     
            logger.debug(">>>>>>>>>>>>>>>>>>>>>>>>putObject:" + key + "=" + value);
            byte[] keyByte=SerializeUtil.serialize(key.toString());
            byte[] valyeByte=SerializeUtil.serialize(value);
//            jedis.set(keyByte,valyeByte);
            jedis.hset(id.getBytes(), keyByte, valyeByte);
        } catch (Exception e) {
            e.printStackTrace();
        }finally{
            ibatisRedisClientImpl.returnResource(jedis);
        }

    }
 
    public Object getObject(Object key) { 
        CacheKey ck=(CacheKey)key;
        IbatisRedisClient ibatisRedisClientImpl=(IbatisRedisClient)SpringUtil.getObject("ibatisRedisClient"); 
        Jedis jedis = ibatisRedisClientImpl.getResource();
        try{                     
            byte[] keyByte=SerializeUtil.serialize(key.toString());
            //byte[] valyeByte=jedis.get(keyByte);
            byte[] valyeByte=jedis.hget(id.getBytes(), keyByte);
             Object value = null;
            if(valyeByte!=null){
                value=SerializeUtil.unserialize(valyeByte);
            }
            logger.debug(">>>>>>>>>>>>>>>>>>>>>>>>getObject:" + key + "=" + value);
            return value;
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }finally{
            ibatisRedisClientImpl.returnResource(jedis);
        }
        return null;
    }
 
    public Object removeObject(Object key) {
        
        IbatisRedisClient ibatisRedisClientImpl=(IbatisRedisClient)SpringUtil.getObject("ibatisRedisClient"); 
        Jedis jedis = ibatisRedisClientImpl.getResource();
        try{                     
            return jedis.expire(SerializeUtil.serialize(key.toString()), 0);
        }finally{
            ibatisRedisClientImpl.returnResource(jedis);
        }
        

    }
 
    public void clear() {
        
        IbatisRedisClient ibatisRedisClientImpl=(IbatisRedisClient)SpringUtil.getObject("ibatisRedisClient"); 
        Jedis jedis = ibatisRedisClientImpl.getResource();
        try{                     
            //jedis.flushDB();
            //jedis.hdel(key, fields);
            Set<byte[]> set=jedis.hkeys(id.getBytes());
            Iterator<byte[]> it=set.iterator();
            while(it.hasNext()){
                byte[] field=it.next();
                jedis.hdel(id.getBytes(), field);
            }
        }finally{
            ibatisRedisClientImpl.returnResource(jedis);
        }
    }
 
    public ReadWriteLock getReadWriteLock() {
        return readWriteLock;
    }
 

 
}

 

4.序列化类

package lq.redis.cache;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;



public class SerializeUtil {
    
    protected static final Logger log = LoggerFactory.getLogger(SerializeUtil.class);

    public static byte[] serialize2(Object object) throws Exception {
        ObjectOutputStream oos = null;
        ByteArrayOutputStream baos = null;
        // 序列化
        baos = new ByteArrayOutputStream();
        oos = new ObjectOutputStream(baos);
        oos.writeObject(object);
        byte[] bytes = baos.toByteArray();
        baos.flush();
        baos.close();
        return bytes;
    }

    public static Object unserialize2(byte[] bytes) throws Exception {
        ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
        // 反序列化
        ObjectInputStream ois = new ObjectInputStream(bais);
        Object result = ois.readObject();
        ois.close();
    
        return result;

    }
    
    public static Object unserialize(byte[] bytes) {
        Object object = null;
        ByteArrayInputStream bais = null;
        ObjectInputStream ois = null;
        try {
            bais = new ByteArrayInputStream(bytes);
            ois = new ObjectInputStream(bais);            
            object = ois.readObject();
            return object;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        } finally {
            if (ois != null) {
                try {
                    ois.close();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
            if (bais != null) {
                try {
                    bais.close();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
        return null;
    }

    public static byte[] serialize(Object obj) {

        ByteArrayOutputStream bos = null;
        ObjectOutputStream oos =null;;
        try {
            bos = new ByteArrayOutputStream();
            oos = new ObjectOutputStream(bos);
            oos.writeObject(obj);
            oos.flush();
            return bos.toByteArray();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            log.error(e.getMessage(), e);
        }finally{
            if(oos!=null){
                try {
                    oos.close();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
            if(bos!=null){
                try {
                    bos.close();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
        return null;
    }
}

 

5.测试类

package lq.redis.cache;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller 
@RequestMapping("resc")
public class RescConstroller { 
    
    @Autowired
    private RescMapper rescMapper;
    

    
    @RequestMapping("getResc.do")
    @ResponseBody
    public void getResc(String id){
        Resc Resc=new Resc();
        Resc.setId(id);
        Resc resRole=rescMapper.getResc(Resc);
        System.out.println(resRole.getNAME());
    }
    
    @RequestMapping("getRescPageList.do")
    @ResponseBody
    public void getRescPageList(){
        Resc Resc=new Resc();
        List<Resc> roleList=rescMapper.getRescPageList(Resc);
        System.out.println(roleList.size());
    }
    
    @RequestMapping("getRescPageCount.do")
    @ResponseBody
    public void getRescPageCount(){
        Resc Resc=new Resc();
        String count=rescMapper.getRescPageCount(Resc);
        System.out.println(count);
    }
    
    
    @RequestMapping("addResc.do")
    @ResponseBody
    public void addResc(){
        Resc Resc=new Resc();
        Resc.setId("5");
        Resc.setNAME("test");
        Resc.setDescn("testtest");
        Resc.setPriority("11");
        Resc.setRes_string("111");
        Resc.setRes_type("111");
        rescMapper.addResc(Resc);
        System.out.println(Resc.getNAME());
    }
    
    @RequestMapping("updateResc.do")
    @ResponseBody
    public void updateResc(){
        Resc Resc=new Resc();
        Resc.setId("3");
        Resc.setNAME("testtest");
        rescMapper.updateResc(Resc);
        System.out.println(Resc.getNAME());
    }
    
    @RequestMapping("delResc.do")
    @ResponseBody
    public void delResc(){
        Resc Resc=new Resc();
        Resc.setId("4");
        rescMapper.delResc(Resc);
        System.out.println(Resc.getNAME());
    }
    
    @RequestMapping("getRescAndRole.do")
    @ResponseBody
    public void getRescAndRole(){
        RescRole rescRole=new RescRole();
        List<RescRole> roleList=rescMapper.getRescAndRole(rescRole);
        for(RescRole temp:roleList){
            System.out.println(temp.getNAME()+":"+temp.getRoleName());
        }
        
    }
    
}

 

1.执行查询语句时候丢进缓存,第二次查询相同语句直接在缓存中取,执行insert,update,del语句刷新该工作空间缓存

 2.假如执行getRescAndRole,缓存了role表和resc的数据,role表f更新时候时候因为getRescAndRole在resc的工作空间(执行resc的ddl操作会更新缓存因为(getRescAndRole在空做空间lq.redis.cache.RescMapper)),所以缓存没没有刷新,导致过期数据,所以

多表跨工作空间要慎重使用

3.多表时候缓存把表放在同一个工作空间 ,获取更新role时候以原数据更新一下resc达到清理缓存目的