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






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值