zoukankan      html  css  js  c++  java
  • Redis整合Mybatis

    将Mybatis的缓存修改成redis缓存

     
    将缓存和数据库分开
     
    首先需要添加依赖
     
    jedis的依赖和mybatis的依赖
    <!-- mybatis依赖 -->  
    <dependency>  
        <groupId>org.mybatis</groupId>  
        <artifactId>mybatis</artifactId>  
        <version>3.2.8</version>  
    </dependency>  
    <!-- jedis 依赖 -->  
     <dependency>  
        <groupId>redis.clients</groupId>  
        <artifactId>jedis</artifactId>  
         <version>2.7.1</version>  
    </dependency>  

    然后我们需要实现Cache类重写里面的方法  

    Cache实现类:
    package cn.et.mybatis.day5.buffer;  
      
    import java.io.ByteArrayInputStream;  
    import java.io.ByteArrayOutputStream;  
    import java.io.IOException;  
    import java.io.ObjectInputStream;  
    import java.io.ObjectOutputStream;  
    import java.util.Set;  
    import java.util.concurrent.locks.ReadWriteLock;  
    import java.util.concurrent.locks.ReentrantReadWriteLock;  
      
    import org.apache.commons.pool2.impl.GenericObjectPoolConfig;  
    import org.apache.ibatis.cache.Cache;  
      
    import redis.clients.jedis.Jedis;  
    import redis.clients.jedis.JedisPool;  
      
      
    public class JedisCache implements Cache {  
        static JedisPool jp=null;  
        private String id;  
        //构造器  
        public JedisCache(String id) {  
            //redis池只需要初始化一次  
            if(jp==null){  
                try {  
                    //关于池的一些配置  
                    GenericObjectPoolConfig gopc=new GenericObjectPoolConfig();  
                    //最大连接数  
                    gopc.setMaxTotal(100);  
                    //最大排队数  
                    gopc.setMaxIdle(10);  
                      
                    //创建一个redis连接池  
                    jp=new JedisPool(gopc, "localhost");  
                    //启动一个redis  检查池创建是否正常  
                    Jedis redis = jp.getResource();  
                    //检查没错就回收回去  
                    jp.returnResourceObject(redis);  
                } catch (Exception e) {  
                      
                    //出错时就不创建redis连接池  
                    jp=null;  
                }  
            }  
            this.id = id;  
        }  
      
        static class SeqUtils{  
            //反序列化为对象  
            public static Object deSer(byte[] bt) throws ClassNotFoundException, IOException{  
                ByteArrayInputStream bais=new ByteArrayInputStream(bt);  
                ObjectInputStream ois=new ObjectInputStream(bais);  
                return ois.readObject();  
            }  
              
            //对象序列化成字节数组  
            public static byte[] ser(Object obj) throws IOException{  
                ByteArrayOutputStream baos=new ByteArrayOutputStream();  
                ObjectOutputStream obos=new ObjectOutputStream(baos);  
                obos.writeObject(obj);  
                return baos.toByteArray();  
            }  
              
        }  
          
          
        @Override  
        public void clear() {  
            Jedis redis = jp.getResource();  
            //将所有的缓存清空 所有对象都清空  
            redis.flushAll();  
              
            jp.returnResourceObject(redis);  
        }  
      
        /** 
         * 这个方法返回的是mapper查询的id 
         * */  
        @Override  
        public String getId() {  
              
            return id;  
        }  
      
        /** 
         * mybatis自动调用该方法 判断返回值是否为null 
         *   如果为空  自动查询数据库   
         *   不为空  直接使用 返回的对象 
         *   key 才是 传入当前查询的oid 主键 
         */  
        //程序一进来首先检查key是否存在如果存在的话就不从数据库查   
        @Override  
        public Object getObject(Object key) {  
            if(jp==null){  
                return null;  
            }  
            Jedis redis = jp.getResource();  
            try {  
                byte[] bs = redis.get(SeqUtils.ser(key));  
                  
                if(bs!=null){  
                    Object obj = SeqUtils.deSer(bs);  
                    jp.returnResourceObject(redis);  
                    return obj;  
                }  
                  
                  
            } catch (IOException e) {  
                  
                e.printStackTrace();  
            } catch (ClassNotFoundException e) {  
                  
                e.printStackTrace();  
            }  
            jp.returnResourceObject(redis);  
              
            return null;  
        }  
      
          
        /** 
         * 非阻塞式io  non-blocking io   
         * */  
        @Override  
        public ReadWriteLock getReadWriteLock() {  
            // TODO Auto-generated method stub  
            return new ReentrantReadWriteLock();  
        }  
      
        /** 
         * 用于读取 redis中缓存了多少元素 
         */  
        @Override  
        public int getSize() {  
              
            Jedis jedis=jp.getResource();  
              
            //表示匹配所有的key  
            Set<String> alllElemebts=jedis.keys("*");  
              
            return alllElemebts.size();  
        }  
      
        /** 
         * 第一次查询数据库后 mybatis会自动调用 该方法将数据写入缓存 
         */  
        @Override  
        public void putObject(Object key, Object value) {  
            if(jp==null){  
                return;  
            }  
              
            Jedis jedis=jp.getResource();  
            try {  
                //因为只能传字节数组  所以我们需要将key和value转成字节数组  
                jedis.set(SeqUtils.ser(key),SeqUtils.ser(value));  
      
            } catch (IOException e) {  
                e.printStackTrace();  
            }  
            jp.returnResourceObject(jedis);  
        }  
      
        /** 
         * 移出缓存中一个键 
         * */  
        @Override  
        public Object removeObject(Object key) {  
            Jedis jedis=jp.getResource();  
              
            try {  
                jedis.del(SeqUtils.ser(key));  
            } catch (IOException e) {  
                e.printStackTrace();  
            }  
              
            jp.returnResourceObject(jedis);  
            return null;  
        }  
      
    }

    然后在配置问价的cache标签中添加你的实现类 表示引用你的实现类:

    <cache type="cn.et.mybatis.day5.buffer.JedisCache"></cache> 
    测试类:
    @Test  
        public void testTwoBuff(){  
            SqlSessionFactory factory = getSession();  
              
            SqlSession session = factory.openSession();  
            SqlSession session1 = factory.openSession();  
              
            BuffMapper bm = session.getMapper(BuffMapper.class);  
            Emp emp = bm.selectEmp("7788");  
              
            //二级缓存 session不能互相干扰 session必须关闭.  
            session.close();  
              
            System.out.println("-------------------------");  
              
            BuffMapper bm1 = session1.getMapper(BuffMapper.class);  
            Emp emp1 = bm1.selectEmp("7788");  
              
            //二级缓存是不相等的  以为用到了序列化和反序列化  两个对象的值是相等的   
            System.out.println(emp==emp1);  
        } 

    他只会去数据库里面查一次

    使用注解

    使用注解需要在类上面添加@CacheNamespace(implementation=JedisCache.class)

    表示你的二级缓存使用你指定的类的

    在方法上面添加一个注解@Options(useCache=true)

    表示开启二级缓存

    添加一点  如果想要在注解中使用二级缓存的话我们需要在类上面添加一个注解

    @CacheNamespace(eviction=FifoCache.class)       紫色部分为Cache的一个子类 表示内存溢出的时候使用什么算法

  • 相关阅读:
    Java面向对象之继承
    ios Block解决循环引用和回传值
    iOS 计算label的高度
    十六进制的颜色
    App调SDK时加判断
    vmware中clone后的工作
    关于python保留几位小数,不进行四舍五入的方法
    git 绑定github
    opensuse ./filezilla: error while loading shared libraries: libpng12.so.0: cannot open shared object file: No such file or directory
    关于opensuse开机登录背景修改后,不生效的问题
  • 原文地址:https://www.cnblogs.com/xushirong/p/7181793.html
Copyright © 2011-2022 走看看