Mybatis集成Redis

3 篇文章 0 订阅
2 篇文章 0 订阅

emp_mapper.xml

<mapper namespace="cn.et.EmpMapper">
	<!--<cache></cache> 启用二级缓存  属性默认 type 指定使用哪个一个缓存类  -->
	<cache type="cn.et.JedisCache"></cache>
	<select id="selectEmp" resultType="cn.et.Emp">
		select * from emp where empno = #{0}
	</select>
</mapper>

JedisCache

package cn.et;

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;

/**
 * 当在查询时会自动实例化JedisCache类并且传入mapper查询的id;
 * @author Ma-PC
 *
 */
public class JedisCache implements Cache {
	
	/**
	 * 用于序列化和反序列化的操作类
	 * @author Ma-PC
	 */
	static class SeqUtils{
		/**
		 * 字节数组反序列化为对象的方法
		 * @param by
		 * @return Object
		 * @throws IOException
		 * @throws ClassNotFoundException 
		 */
		public static Object deSer(byte[] by) throws IOException, ClassNotFoundException{
			ByteArrayInputStream bais = new ByteArrayInputStream(by);
			ObjectInputStream ois = new ObjectInputStream(bais);
			return ois.readObject();
		}
		
		/**
		 * 对象序列化成字节数组的方法
		 * @param obj
		 * @return	byte[]
		 * @throws IOException
		 */
		public static byte[] ser(Object obj) throws IOException{
			ByteArrayOutputStream baos = new ByteArrayOutputStream();
			ObjectOutputStream obos = new ObjectOutputStream(baos);
			obos.writeObject(obj);
			return baos.toByteArray();
		}
		
	}
	
	private static JedisPool jp = null;
	
	private String id ;
	
	public JedisCache(String id) {
		if(jp == null){
			//当redis出现异常时,将连接池设为null;
			//目的是将redis与数据库完全分离达到高可用性;
			try {
				//设置连接池属性的类
				GenericObjectPoolConfig gopc = new GenericObjectPoolConfig();
				jp = new JedisPool(gopc, "localhost");
				jp.getResource();
			} catch (Exception e) {
				//e.printStackTrace();
				jp=null;
			}
		}
		this.id = id;
	}
	
	public String getId() {
	
		return id;
	}
	
	/**
	 * 第一次查询数据后 会调用putObject将数据写入到缓存中;
	 */
	public void putObject(Object key, Object value) {
		//到连接池为null时,不写入数据
		if(jp==null){
			return ;
		}
		
		Jedis jedis = jp.getResource();
		try {
			jedis.set(SeqUtils.ser(key), SeqUtils.ser(value));
			//将缓存中的数据保存到本地文件;
			//jedis.save();
			//将redis对象回收到连接池中;
			jp.returnResourceObject(jedis);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 自动调用该方法 当返回为null时自动查询数据库
	 * 否则直接使用返回的对象
	 * key 其实就是 oId;
	 */
	public Object getObject(Object key) {
		//当连接池为null时,直接查询数据库
		if(jp==null){
			return null;
		}	
		Jedis jedis = jp.getResource();
		try {
			byte[] be =jedis.get(SeqUtils.ser(key));
			if(be != null){
				Object obj = SeqUtils.deSer(be);
				//将redis对象回收到连接池中;
				jp.returnResourceObject(jedis);
				return obj;
			}
		} catch (IOException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		return null;
	}
	
	/**
	 * 调用了例如 mybatis 的 flush方法  清空缓存
	 * 就会自动调用removeObject清空该元素
	 */
	public Object removeObject(Object key) {
		Jedis jedis = jp.getResource();
		try {
			jedis.del(SeqUtils.ser(key));
			//将redis对象回收到连接池中;
			jp.returnResourceObject(jedis);
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}
	
	/**
	 *清空所有缓存 
	 */
	public void clear() {
		Jedis jedis = jp.getResource();
		jedis.flushAll();
		//将redis对象回收到连接池中;
		jp.returnResourceObject(jedis);
	}
	
	/**
	 * 用于获取redis中缓存了多少元素
	 */
	public int getSize() {
		Jedis jedis = jp.getResource();
		//*表示所有
		Set<String> allElemebts = jedis.keys("*");
		return allElemebts.size();
	}
	
	/**
	 * 非阻塞式io  non-blocking io 简单可以理解成 异步调用的io流
	 * 处理读写相同数据时的线程安全问题
	 */
	public ReadWriteLock getReadWriteLock() {
		
		return new ReentrantReadWriteLock();
	}

}


Test

/**
	 * 二级缓存
	 * @param args
	 */
	public static void main(String[] args) {
		
		SqlSessionFactory factory = getSqlSessionFactory();
		
		SqlSession session = factory.openSession();
		EmpMapper dm = session.getMapper(EmpMapper.class);
		Emp emp = dm.selectEmp("7369");
		//开启二级缓存后  关闭session时   
		//session中一级缓存的数据会自动发往二级缓存
		session.close();
		
		//打开第二个SqlSession
		SqlSession session2 = factory.openSession();
		//通过sqlSession2获取EmpMapper实例
		EmpMapper em = session2.getMapper(EmpMapper.class);
		Emp selectEmp = em.selectEmp("7369");
		System.out.println(emp==selectEmp);
	}


Run

第一次运行:第一次到数据库查询后,写入缓存中,往后相同的查询直接使用缓存中的数据
2017-07-13 10:35:34 DEBUG [cn.et..EmpMapper.selectEmp] ==>  Preparing: select * from emp where empno = ? 
2017-07-13 10:35:34 DEBUG [cn.et.EmpMapper.selectEmp] ==> Parameters: 7369(String)
2017-07-13 10:35:34 DEBUG [cn.et.EmpMapper.selectEmp] <==      Total: 1
2017-07-13 10:35:34 DEBUG [org.apache.ibatis.transaction.jdbc.JdbcTransaction] Resetting autocommit to true on JDBC Connection [oracle.jdbc.driver.T4CConnection@dc85d20]
2017-07-13 10:35:34 DEBUG [org.apache.ibatis.transaction.jdbc.JdbcTransaction] Closing JDBC Connection [oracle.jdbc.driver.T4CConnection@dc85d20]
2017-07-13 10:35:34 DEBUG [org.apache.ibatis.datasource.pooled.PooledDataSource] Returned connection 231234848 to pool.
2017-07-13 10:35:34 DEBUG [cn.et.EmpMapper] Cache Hit Ratio [cn.et.lesson05.EmpMapper]: 0.5


第二次运行:

2017-07-13 10:37:35 DEBUG [cn.et.EmpMapper] Cache Hit Ratio [cn.et.EmpMapper]: 1.0
2017-07-13 10:37:35 DEBUG [cn.et.EmpMapper] Cache Hit Ratio [cn.et.EmpMapper]: 1.0


第三次关闭Redis服务器后运行 :

2017-07-13 10:40:09 DEBUG [cn.et.EmpMapper.selectEmp] ==>  Preparing: select * from emp where empno = ? 
2017-07-13 10:40:09 DEBUG [cn.et.EmpMapper.selectEmp] ==> Parameters: 7369(String)
2017-07-13 10:40:09 DEBUG [cn.et.EmpMapper.selectEmp] <==      Total: 1
2017-07-13 10:40:09 DEBUG [org.apache.ibatis.transaction.jdbc.JdbcTransaction] Resetting autocommit to true on JDBC Connection [oracle.jdbc.driver.T4CConnection@fd1c5f4]
2017-07-13 10:40:09 DEBUG [org.apache.ibatis.transaction.jdbc.JdbcTransaction] Closing JDBC Connection [oracle.jdbc.driver.T4CConnection@fd1c5f4]
2017-07-13 10:40:09 DEBUG [org.apache.ibatis.datasource.pooled.PooledDataSource] Returned connection 265405940 to pool.
2017-07-13 10:40:09 DEBUG [cn.et.EmpMapper] Cache Hit Ratio [cn.et.EmpMapper]: 0.0
2017-07-13 10:40:09 DEBUG [org.apache.ibatis.transaction.jdbc.JdbcTransaction] Opening JDBC Connection
2017-07-13 10:40:09 DEBUG [org.apache.ibatis.datasource.pooled.PooledDataSource] Checked out connection 265405940 from pool.
2017-07-13 10:40:09 DEBUG [org.apache.ibatis.transaction.jdbc.JdbcTransaction] Setting autocommit to false on JDBC Connection [oracle.jdbc.driver.T4CConnection@fd1c5f4]
2017-07-13 10:40:09 DEBUG [cn.et.EmpMapper.selectEmp] ==>  Preparing: select * from emp where empno = ? 
2017-07-13 10:40:09 DEBUG [cn.et.EmpMapper.selectEmp] ==> Parameters: 7369(String)
2017-07-13 10:40:09 DEBUG [cn.et.EmpMapper.selectEmp] <==      Total: 1


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值