zoukankan      html  css  js  c++  java
  • Redis之实战篇(与Mybatis整合)

    摘要: 现在市面流行的java框架,一个是ssh(spring、struts2、hibernate),另一个是ssm(spring、springmvc、mybatis),由于之前已经有整合过ssm框架,所以在此基础上进行略微的改动,做一个Redis与Mybatis的整合

    具体步骤如下:

    1,准备好ssm工程,如果有不会的,可以参考

    springmvc+mybatis整合

    2,准备好Redis服务器

    3,构建 pom.xml 文件,这个pom文件和之前ssm的基本一样,只是添加了redis的支持

    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    	<modelVersion>4.0.0</modelVersion>
    	<groupId>com.demo</groupId>
    	<artifactId>demo</artifactId>
    	<packaging>war</packaging>
    	<version>0.0.1-SNAPSHOT</version>
    	<name>demo Maven Webapp</name>
    	<properties>
    		<!-- spring版本号 -->
    		<spring.version>4.2.2.RELEASE</spring.version>
    		<!-- mybatis版本号 -->
    		<mybatis.version>3.3.0</mybatis.version>
    		<!-- log4j日志文件管理包版本 -->
    		<slf4j.version>1.7.7</slf4j.version>
    		<log4j.version>1.2.17</log4j.version>
    	</properties>
    
    	<dependencies>
    		<dependency>
    		    <groupId>jdk.tools</groupId>
    		    <artifactId>jdk.tools</artifactId>
    		    <version>1.7</version>
    		    <scope>system</scope>
    		    <systemPath>${JAVA_HOME}/lib/tools.jar</systemPath>
    		</dependency>
    		<dependency>
    			<groupId>junit</groupId>
    			<artifactId>junit</artifactId>
    			<version>4.11</version>
    			<!-- 表示开发的时候引入,发布的时候不会加载此包 -->
    			<scope>test</scope>
    		</dependency><!-- spring核心包 --><dependency><groupId>org.springframework</groupId><artifactId>spring-core</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-web</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-oxm</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-tx</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-aop</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-context-support</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-test</artifactId><version>${spring.version}</version></dependency><!-- mybatis核心包 --><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>${mybatis.version}</version></dependency><!-- mybatis/spring包 --><dependency><groupId>org.mybatis</groupId><artifactId>mybatis-spring</artifactId><version>1.2.2</version></dependency><!-- 导入java ee jar 包 --><dependency><groupId>javax</groupId><artifactId>javaee-api</artifactId><version>7.0</version></dependency><!-- 导入Mysql数据库链接jar包 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.30</version></dependency><!-- 导入dbcp的jar包,用来在applicationContext.xml中配置数据库 --><dependency><groupId>commons-dbcp</groupId><artifactId>commons-dbcp</artifactId><version>1.2.2</version></dependency><!-- JSTL标签类 --><dependency><groupId>jstl</groupId><artifactId>jstl</artifactId><version>1.2</version></dependency><!-- 日志文件管理包 --><!-- log start --><dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>${log4j.version}</version></dependency><!-- 格式化对象,方便输出日志 --><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.1.41</version></dependency><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId><version>${slf4j.version}</version></dependency><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-log4j12</artifactId><version>${slf4j.version}</version></dependency><!-- log end --><!-- 映入JSON --><dependency><groupId>org.codehaus.jackson</groupId><artifactId>jackson-mapper-asl</artifactId><version>1.9.13</version></dependency><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-core</artifactId><version>2.1.0</version></dependency><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.1.0</version></dependency><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-annotations</artifactId><version>2.1.0</version></dependency><!-- 上传组件包 --><dependency><groupId>commons-fileupload</groupId><artifactId>commons-fileupload</artifactId><version>1.3.1</version></dependency><dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>2.4</version></dependency><dependency><groupId>commons-codec</groupId><artifactId>commons-codec</artifactId><version>1.9</version></dependency><dependency>
    		  <groupId>redis.clients</groupId>
    		  <artifactId>jedis</artifactId>
    		  <version>2.8.0</version></dependency><dependency>
    		  <groupId>commons-pool</groupId>
    		  <artifactId>commons-pool</artifactId>
    		  <version>1.6</version></dependency></dependencies><build><finalName>${project.artifactId}</finalName><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>2.3.2</version><configuration><source>${java-version}</source><target>${java-version}</target><encoding>utf8</encoding></configuration></plugin></plugins></build></project>

    4,编写Redis需要用的2个工具类   RedisUtil.java和SerializeUtil.java。这个在前一篇已经有过,这里不再重复贴代码了。

    5,新增一个Cache类,需要实现 org.apache.ibatis.cache.Cache 接口

    package demo.cache;
    
    import java.util.concurrent.locks.ReadWriteLock;
    import java.util.concurrent.locks.ReentrantReadWriteLock;
    import org.apache.ibatis.cache.Cache;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import demo.utils.RedisUtil;
    import demo.utils.SerializeUtil;
    
    public class MybatisRedisCache implements Cache {
    	private static Logger logger = LoggerFactory.getLogger(MybatisRedisCache.class); 
    	/** The ReadWriteLock. */ 
    	private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
    	
    	private String id;
    	
    	public MybatisRedisCache(final String id) {  
    		if (id == null) {
                throw new IllegalArgumentException("Cache instances require an ID");
            }
    		logger.debug(">>>>>>>>>>>>>>>>>>>>>>>>MybatisRedisCache:id="+id);
            this.id = id;
        }  
    	
    	public String getId() {
    		return this.id;
    	}
    
    	public void putObject(Object key, Object value) {
    		logger.debug(">>>>>>>>>>>>>>>>>>>>>>>>putObject:"+key+"="+value);
    		RedisUtil.getJedis().set(SerializeUtil.serialize(key.toString()), SerializeUtil.serialize(value));
    	}
    
    	public Object getObject(Object key) {
    		Object value = SerializeUtil.unserialize(RedisUtil.getJedis().get(SerializeUtil.serialize(key.toString())));
    		logger.debug(">>>>>>>>>>>>>>>>>>>>>>>>getObject:"+key+"="+value);
    		return value;
    	}
    
    	public Object removeObject(Object key) {
    		return RedisUtil.getJedis().expire(SerializeUtil.serialize(key.toString()),0);
    	}
    
    	public void clear() {
    		RedisUtil.getJedis().flushDB();
    	}
    
    	public int getSize() {
    		return Integer.valueOf(RedisUtil.getJedis().dbSize().toString());
    	}
    
    	public ReadWriteLock getReadWriteLock() {
    		return readWriteLock;
    	}
    	
    }

    6,开启mybatis对缓存的支持,在本项目中,是修改 spring-mybatis.xml 文件

    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    		<property name="dataSource" ref="dataSource" />
    		<!-- 自动扫描mapping.xml文件 -->
    		<property name="mapperLocations" value="classpath:demo/mapping/*.xml"></property>
    		<property name="configurationProperties">
    			<props>
    				<prop key="cacheEnabled">true</prop> 
    				<prop key="lazyLoadingEnabled">false</prop> 
    				<prop key="aggressiveLazyLoading">true</prop>
    			</props>
    		</property>
    	</bean>

    其中:

    <prop key="cacheEnabled">true</prop>

    是开启的关键。

    7,在相关的 mapper.xml 添加所需要用的缓存类,我们这里是在 TUserMapper.xml 中添加

    <?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="demo.dao.TUserMapper">
    
    	<cache type="demo.cache.MybatisRedisCache" />
    	
    	<resultMap id="BaseResultMap" type="demo.domain.TUser">
    		<id column="id" property="id" jdbcType="INTEGER" />
    		<result column="username" property="username" jdbcType="VARCHAR" />
    		<result column="password" property="password" jdbcType="VARCHAR" />
    		<result column="createtime" property="createtime" jdbcType="TIMESTAMP" />
    	</resultMap>
    	<sql id="Base_Column_List">
    		id, username, password, createtime
    	</sql>
    	<select id="selectByPrimaryKey" resultMap="BaseResultMap"
    		parameterType="java.lang.Integer">
    		select <include refid="Base_Column_List" /> from t_user where id = #{id,jdbcType=INTEGER}
    	</select>
    	<delete id="deleteByPrimaryKey" parameterType="java.lang.Integer">
    		delete from t_user
    		where id = #{id,jdbcType=INTEGER}
    	</delete>
    	<insert id="insert" parameterType="demo.domain.TUser">
    		insert into t_user (id, username, password,
    		createtime)
    		values (#{id,jdbcType=INTEGER}, #{username,jdbcType=VARCHAR},
    		#{password,jdbcType=VARCHAR},
    		#{createtime,jdbcType=TIMESTAMP})
    	</insert><insert id="insertSelective" parameterType="demo.domain.TUser">
    		insert into t_user
    		<trim prefix="(" suffix=")" suffixOverrides=","><if test="id != null">
    				id,
    			</if><if test="username != null">
    				username,
    			</if><if test="password != null">
    				password,
    			</if><if test="createtime != null">
    				createtime,
    			</if></trim><trim prefix="values (" suffix=")" suffixOverrides=","><if test="id != null">
    				#{id,jdbcType=INTEGER},
    			</if><if test="username != null">
    				#{username,jdbcType=VARCHAR},
    			</if><if test="password != null">
    				#{password,jdbcType=VARCHAR},
    			</if><if test="createtime != null">
    				#{createtime,jdbcType=TIMESTAMP},
    			</if></trim></insert><update id="updateByPrimaryKeySelective" parameterType="demo.domain.TUser">
    		update t_user
    		<set><if test="username != null">
    				username = #{username,jdbcType=VARCHAR},
    			</if><if test="password != null">
    				password = #{password,jdbcType=VARCHAR},
    			</if><if test="createtime != null">
    				createtime = #{createtime,jdbcType=TIMESTAMP},
    			</if></set>
    		where id = #{id,jdbcType=INTEGER}</update><update id="updateByPrimaryKey" parameterType="demo.domain.TUser">
    		update t_user
    		set username = #{username,jdbcType=VARCHAR},
    		password = #{password,jdbcType=VARCHAR},
    		createtime = #{createtime,jdbcType=TIMESTAMP}
    		where id = #{id,jdbcType=INTEGER}</update><select id="selectAll" resultMap="BaseResultMap">
    		select <include refid="Base_Column_List" /> from t_user
    	</select></mapper>

    其中:

    <cache type="demo.cache.MybatisRedisCache" />

    是关键。

    然后就可以在自己写的测试类或者controller中做测试了,测试的时候可以把日志级别设置为debug级别,这样可以看到Mybatis的sql语句。当走缓存的时候,是不会打印sql语句的,反之会出现sql语句。

    例如,我们在原有的数据里,新加了一条数据,这时缓存数据和数据库数据就对应不上,可以看到日志里有sql语句打印

    [org.mybatis.spring.SqlSessionUtils] - Creating a new SqlSession
    [org.mybatis.spring.SqlSessionUtils] - SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1005765] was not registered for synchronization because synchronization is not active
    [demo.cache.MybatisRedisCache] - >>>>>>>>>>>>>>>>>>>>>>>>getObject:-1445659396:380449231:demo.dao.TUserMapper.selectAll:0:2147483647:select  
    		id, username, password, createtime
    	  from t_user:SqlSessionFactoryBean=null
    [demo.dao.TUserMapper] - Cache Hit Ratio [demo.dao.TUserMapper]: 0.0
    [org.springframework.jdbc.datasource.DataSourceUtils] - Fetching JDBC Connection from DataSource
    [org.mybatis.spring.transaction.SpringManagedTransaction] - JDBC Connection [jdbc:mysql://127.0.0.1:3306/demo, UserName=root@localhost, MySQL Connector Java] will not be managed by Spring
    [demo.dao.TUserMapper.selectAll] - ==>  Preparing: select id, username, password, createtime from t_user 
    [demo.dao.TUserMapper.selectAll] - ==> Parameters: 
    [demo.dao.TUserMapper.selectAll] - <==      Total: 9
    [demo.cache.MybatisRedisCache] - >>>>>>>>>>>>>>>>>>>>>>>>putObject:-1445659396:380449231:demo.dao.TUserMapper.selectAll:0:2147483647:select  
    		id, username, password, createtime
    	  from t_user:SqlSessionFactoryBean=[demo.domain.TUser@4f6d47, demo.domain.TUser@8f7ea3, demo.domain.TUser@c309e0, demo.domain.TUser@bd7ea6, demo.domain.TUser@c5fc10, demo.domain.TUser@2784fd, demo.domain.TUser@8c0b75, demo.domain.TUser@443aea, demo.domain.TUser@177e204]

    一旦这个执行过一次后,再执行(不再有数据变更),可以看到,也就不再有sql语句的打印了。

    [org.mybatis.spring.SqlSessionUtils] - Creating a new SqlSession
    [org.mybatis.spring.SqlSessionUtils] - SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@b14a45] was not registered for synchronization because synchronization is not active
    [demo.cache.MybatisRedisCache] - >>>>>>>>>>>>>>>>>>>>>>>>getObject:-1445659396:380449231:demo.dao.TUserMapper.selectAll:0:2147483647:select  
    		id, username, password, createtime
    	  from t_user:SqlSessionFactoryBean=[demo.domain.TUser@78471b, demo.domain.TUser@847332, demo.domain.TUser@1a6f080, demo.domain.TUser@f78840, demo.domain.TUser@11232a8, demo.domain.TUser@1bbe24e, demo.domain.TUser@672d9, demo.domain.TUser@15e2565, demo.domain.TUser@1e93ee7]
    [demo.dao.TUserMapper] - Cache Hit Ratio [demo.dao.TUserMapper]: 0.6666666666666666
    [org.mybatis.spring.SqlSessionUtils] - Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@b14a45]
    [demo.domain.TUser@78471b, demo.domain.TUser@847332, demo.domain.TUser@1a6f080, demo.domain.TUser@f78840, demo.domain.TUser@11232a8, demo.domain.TUser@1bbe24e, demo.domain.TUser@672d9, demo.domain.TUser@15e2565, demo.domain.TUser@1e93ee7]

    备注:在网上看到有些人说mybatis和redis整合的时候,数据库使用mysql总是加载第一页的数据,不会显示以后的数据,经测试,可以正确加载指定页数的数据,分页也是采用常规的分页方法,这里就不再做描述了。

    -------------------------------2016-5-12更新SerializeUtil.java------------------------

    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) {
            ByteArrayInputStream bais = null;
            try {
                // 反序列化
                bais = new ByteArrayInputStream(bytes);
                ObjectInputStream ois = new ObjectInputStream(bais);
                return ois.readObject();
            } catch (Exception e) {
            	e.printStackTrace();
            }
            return null;
        }
    }
     
  • 相关阅读:
    Algs4-1.3.44文本编辑器的缓冲区
    Algs4-1.3.42复制栈
    Algs4-1.3.41复制队列采用for方式实现
    Algs4-1.3.39环形缓冲区
    Algs4-1.3.40前移编码
    Algs4-1.3.38删除第k个元素-数组实现
    安全测试的一些漏洞和测试方法
    Java内存自动回收,为什么会有内存泄露?
    三款主流静态源代码安全检测工具比较
    Fortify源码安全检测工具
  • 原文地址:https://www.cnblogs.com/dogdogwang/p/7102998.html
Copyright © 2011-2022 走看看