文档章节

Mybatis整合 Redis实现 Cache

放下不下
 放下不下
发布于 2016/09/22 17:36
字数 758
阅读 125
收藏 4

Mybatis为了方便我们扩展缓存定义了一个Cache接口,我们可以使用这个接口实现第三方缓存, ##下面我们来看代码实现: ###1.实现cache接口

package com.gat.jd.util;

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

import org.apache.ibatis.cache.Cache;
import org.slf4j.LoggerFactory;

import redis.clients.jedis.Jedis;
import redis.clients.util.SafeEncoder;

import com.gat.common.redis.RedisCallback;
import com.gat.common.redis.RedisConfig;
import com.gat.common.redis.RedisConfigBuilder;
/**
 * 
 * @author DaiXiaoWei
 *
 */
public class MybatisRedisCache implements Cache {
	private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(MybatisRedisCache.class);
	/** The ReadWriteLock. */
	private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
	private static RedisConfig redisConfig = new RedisConfigBuilder("redisjava.properties").parseConfig();

	private static final String TOTAL_PREFIX = "JD_DB_";

	private String id;

	private byte[] redisKey;

	public MybatisRedisCache(final String id) {
		if (id == null) {
			throw new IllegalArgumentException("缓存没有初始化id");
		}

		LOGGER.info("==================MyBatisRedisCache:id=" + id);
		this.id = id;
		redisKey = SafeEncoder.encode(TOTAL_PREFIX + id);
	}

	public String getId() {
		return this.id;
	}

	public void putObject(final Object key, final Object value) {
		redisConfig.execute(new RedisCallback<String>() {

			@Override
			public String call(Jedis jedis) {
				jedis.hset(redisKey, SerializeUtil.serialize(key.toString()), SerializeUtil.serialize(value));
				jedis.expire(redisKey, 3600);
				return null;
			}
		});
	}

	public Object getObject(final Object key) {
		return redisConfig.execute(new RedisCallback<Object>() {

			@Override
			public Object call(Jedis jedis) {
				byte[] valueBytes = jedis.hget(redisKey, SerializeUtil.serialize(key.toString()));
				Object value = SerializeUtil.unserialize(valueBytes);
				return value;
			}
		});

	}

	public Object removeObject(final Object key) {
		return redisConfig.execute(new RedisCallback<Object>() {

			@Override
			public Object call(Jedis jedis) {
				jedis.hdel(redisKey, SerializeUtil.serialize(key.toString()));
				return 1;
			}
		});

	}

	public void clear() {
		redisConfig.execute(new RedisCallback<Object>() {

			@Override
			public Object call(Jedis jedis) {
				jedis.del(redisKey);
				return null;
			}
		});
	}

	public int getSize() {
		return redisConfig.execute(new RedisCallback<Integer>() {

			@Override
			public Integer call(Jedis jedis) {
				return jedis.hlen(redisKey).intValue();
			}
		});
	}

	public ReadWriteLock getReadWriteLock() {
		return readWriteLock;
	}

}

注意:这边每一个namespace都有一个redisKey与之对应, mybatis的二级缓存的范围是命名空间(namespace),当同一个命名空间有一个 insert、update、delete 操作mybatis 就会把这个命名空间下的二级缓清空,这里是通过删除redisKey实现的。

#2.用到的一些其它类 ##2.1 序列化类

package com.gat.jd.util;

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

import org.apache.commons.io.output.ByteArrayOutputStream;



public class SerializeUtil {
    /**
     * 序列化
     * @param object
     */
    public static byte[] serialize(Object object) {
        ObjectOutputStream oos = null;
        ByteArrayOutputStream baos = null;
        try {
            // 序列化
            baos = new ByteArrayOutputStream();
            oos = new ObjectOutputStream(baos);
            oos.writeObject(object);
            byte[] bytes = baos.toByteArray();
            return bytes;
        } catch (Exception e) {
        	e.printStackTrace();
        }
        return null;
    }

    /**
     * 反序列化
     * @param bytes
     */
    public static Object unserialize(byte[] bytes) {
    	if (bytes == null)  
            return null;  
        ByteArrayInputStream bais = null;
        try {
            // 反序列化
            bais = new ByteArrayInputStream(bytes);
            ObjectInputStream ois = new ObjectInputStream(bais);
            return ois.readObject();
        } catch (Exception e) {
        	e.printStackTrace();
        }
        return null;
    }
}

##2.2 redis配置文件redisjava.properties

host=192.168.30.60
port=6379
connectionTimeout=
soTimeout=
password=
database=5

##3.在mapper文件中添加这个我们自定义的缓存

<?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="com.gat.jd.dao.base.KeyWordDao">
	<cache type="com.gat.jd.util.MybatisRedisCache" />

##4.下面看看日志输出: ###4.1第一次访问

 INFO 2016-09-20 10:34:13 [com.gat.jd.util.MybatisRedisCache:63] >>>>>>>>>>>>>>>>>>>>>>>>getObject:1870846166:3481599681:com.gat.jd.dao.base.KeyWordDao.getKeyWord:0:2147483647:SELECT
		keyword
		FROM
		`Keyword`:SqlSessionFactoryBean,value:null
  INFO 2016-09-20 10:34:13 [com.gat.jd.util.MybatisRedisCache:47] >>>>>>>>>>>>>>>>>>>>>>>>putObject:1870846166:3481599681:com.gat.jd.dao.base.KeyWordDao.getKeyWord:0:2147483647:SELECT
		keyword
		FROM
		`Keyword`:SqlSessionFactoryBean,value:[七夕礼品, 玫瑰, 月饼, 手机, iPhone]

###4.2第二次访问:

 INFO 2016-09-20 15:17:22 [com.gat.jd.util.MybatisRedisCache:61] >>>>>>>>>>>>>>>>>>>>>>>>getObject:1870846166:3481599681:com.gat.jd.dao.base.KeyWordDao.getKeyWord:0:2147483647:SELECT
		keyword
		FROM
		`Keyword`:SqlSessionFactoryBean,value:[七夕礼品, 玫瑰, 月饼, 手机, iPhone]
 DEBUG 2016-09-20 15:17:22 [com.gat.jd.dao.base.KeyWordDao:62] Cache Hit Ratio [com.gat.jd.dao.base.KeyWordDao]: 1.0

从结果看到我们第二次访问命中了缓存

#5.简单总结一下: ###1.如果对一个namespace增删改很频繁的话不建议加缓存,因为每次增删改都会清空整个namespace下的其它缓存,查询再次重新创建,消耗资源。 ###2.对数据库修改会调用cache的clear方法,clear不建议调用redis的flushDB方法,这样会清空整个db下的key。

© 著作权归作者所有

放下不下
粉丝 0
博文 1
码字总数 758
作品 0
徐汇
高级程序员
私信 提问
Redis之实战篇(与Mybatis整合)

具体步骤如下: 1,准备好ssm工程,如果有不会的,可以参考 springmvc+mybatis整合 2,准备好Redis服务器 3,构建 pom.xml 文件,这个pom文件和之前ssm的基本一样,只是添加了redis的支持 4,...

Fraud
2016/01/08
3.4K
8
spring cache + redis整合

谨以此做个笔记。 平时我们使用的redis无非是用作缓存以及分布式session,其他的作用就视项目需求而定了。 这里主要讲讲redis作为缓存的作用。 使用redis做缓存,可以选择单独使用,也可以和...

疯狂的米老鼠
2017/12/11
0
0
redis+mybatis+spring

redis的安装http://liuyieyer.iteye.com/blog/2078093 redis的主从高可用 http://liuyieyer.iteye.com/blog/2078095 Mybatis 的使用不多说。 Mybatis为了方便我们扩展缓存定义了一个Cache接口...

凯文加内特
2016/01/21
518
0
Mybatis应用学习(5)——查询缓存

什么是查询缓存 1. Mybatis提供了查询缓存的功能,用于减轻数据库查询压力,分别提供了一级缓存和二级缓存两种缓存级别。 2. 查询缓存,就是将SQL查询语句查询的结果缓存中内存中(通过HashM...

江左煤郎
2018/11/27
28
0
Mybatis学习系列(七)缓存机制

Mybatis缓存介绍 MyBatis提供一级缓存和二级缓存机制。 一级缓存是Sqlsession级别的缓存,Sqlsession类的实例对象中有一个hashmap用于缓存数据。不同的Sqlsession实例直接hashmap互不影响。M...

仍是少年
2018/07/12
0
0

没有更多内容

加载失败,请刷新页面

加载更多

视频如何加水印?

很多视频制作者的视频都被他人盗用过,为了防止自己的劳动成果被他人窃取,给视频加水印对于视频制作者来说,是一件非常重要的事情。那么下面分享一个手机给视频加水印的方法,一起来看看吧!...

白米稀饭2019
25分钟前
5
0
004-Envelop-基于Blockstack的文件传输dapp

本篇文章主要介绍基于Blockstack的文件传输工具; ####A-链接地址 官网地址:https://envelop.app/ Github地址:https://github.com/envelop-app ####B-特性: 1: Share private files easil...

Riverzhou
28分钟前
6
0
SpringCloud——声明式调用Feign

Feign声明式调用 一、Feign简介 使用Ribbon和RestTemplate消费服务的时候,有一个最麻烦的点在于,每次都要拼接URL,组织参数,所以有了Feign声明式调用,Feign的首要目标是将Java HTTP客户端...

devils_os
34分钟前
7
0
《JAVA核心知识》学习笔记 (22. 数据结构)

22.1.1. 栈(stack) 栈( stack)是限制插入和删除只能在一个位置上进行的表,该位置是表的末端,叫做栈顶 (top)。它是后进先出(LIFO)的。对栈的基本操作只有 push(进栈)和 pop(出栈...

Shingfi
39分钟前
6
0
你对AJAX认知有多少(1)?

AJAX(一) AJAX技术对于前段或者后端工程师来说,都是必不可缺的 那我们这几期都来细细品味一下AJAX的相关知识,直接上干货喽~ 1、什么是AJAX,为什么要使用Ajax(请谈一下你对Ajax的认识) 什么...

理性思考
47分钟前
14
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部