• 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的一个子类 表示内存溢出的时候使用什么算法

  • 相关阅读:
    都为你整理好了,5种Java 随机方式对比!你都知道吗?
    你不知道的,Java代码性能优化的 40+ 细节,赶快收藏!
    大厂技术总监,送给刚毕业和快要毕业的程序员——7点建议
    .NET Core 微服务学习与实践系列文章目录索引(2019版)
    ManagementEventWatcher throws ManagementException with call to Stop()
    postman工具的使用
    java实体类读取属性文件,并赋值
    使用idea创建springboot的maven项目
    手写Promise实现过程
    用Javascript制作随机星星效果图
  • 原文地址:https://www.cnblogs.com/xushirong/p/7181793.html
Copyright © 2020-2023  润新知