1. 程式人生 > >redis作為mybatis的二級快取

redis作為mybatis的二級快取

redis作為二級快取伺服器,來替代mybatis的二級快取,至於二級快取有什麼缺點我想大家都懂吧,

 

[service] 2016-08-31 21:01:32,912 - com.erp.dao.TestMybatisMapper.selectByPrimaryKey -19446 [http-nio-8080-exec-6] DEBUG com.erp.dao.TestMybatisMapper.selectByPrimaryKey  - ==>  Preparing: select TID, TNAME from TESTMYBATIS where TID = ? 
    [service] 2016-08-31 21:01:32,912 - com.erp.dao.TestMybatisMapper.selectByPrimaryKey -19446 [http-nio-8080-exec-6] DEBUG com.erp.dao.TestMybatisMapper.selectByPrimaryKey  - ==> Parameters: 6(BigDecimal)
    [service] 2016-08-31 21:01:32,944 - com.erp.dao.TestMybatisMapper.selectByPrimaryKey -19478 [http-nio-8080-exec-6] DEBUG com.erp.dao.TestMybatisMapper.selectByPrimaryKey  - <==      Total: 1
    [service] 2016-08-31 21:01:32,945 - com.erp.utils.redcache.RedisCache -19479 [http-nio-8080-exec-6] DEBUG com.erp.utils.redcache.RedisCache  - >>>>>>>>>>>>>>>>>>>>>>>>putObject:1716629384:864926724:com.erp.dao.TestMybatisMapper.selectByPrimaryKey:0:2147483647:select 
     
    TID, TNAME
   
    from TESTMYBATIS
    where TID = ?:6=[TestMybatis [tid=6, tname=asd]]
    [service] 2016-08-31 21:01:32,946 - org.mybatis.spring.SqlSessionUtils -19480 [http-nio-8080-exec-6] DEBUG org.mybatis.spring.SqlSessionUtils  - Closing non transactional SqlSession [
[email protected]
] [service] 2016-08-31 21:01:32,946 - org.springframework.jdbc.datasource.DataSourceUtils -19480 [http-nio-8080-exec-6] DEBUG org.springframework.jdbc.datasource.DataSourceUtils - Returning JDBC Connection to DataSource TestMybatis [tid=6, tname=asd] [service] 2016-08-31 21:01:32,947 - org.springframework.web.servlet.DispatcherServlet -19481 [http-nio-8080-exec-6] DEBUG org.springframework.web.servlet.DispatcherServlet - Null ModelAndView returned to DispatcherServlet with name 'springMVC': assuming HandlerAdapter completed request handling
[service] 2016-08-31 21:12:33,225 - org.springframework.web.servlet.DispatcherServlet -23378 [http-nio-8080-exec-10] DEBUG org.springframework.web.servlet.DispatcherServlet  - Last-Modified value for [/mybatisRedis/s] is: -1
    [service] 2016-08-31 21:12:33,243 - org.mybatis.spring.SqlSessionUtils -23396 [http-nio-8080-exec-10] DEBUG org.mybatis.spring.SqlSessionUtils  - Creating a new SqlSession
    [service] 2016-08-31 21:12:33,251 - org.mybatis.spring.SqlSessionUtils -23404 [http-nio-8080-exec-10] DEBUG org.mybatis.spring.SqlSessionUtils  - SqlSession [
[email protected]
] was not registered for synchronization because synchronization is not active [service] 2016-08-31 21:12:33,477 - com.erp.utils.redcache.RedisCache -23630 [http-nio-8080-exec-10] DEBUG com.erp.utils.redcache.RedisCache - >>>>>>>>>>>>>>>>>>>>>>>>getObject:1716629384:864926724:com.erp.dao.TestMybatisMapper.selectByPrimaryKey:0:2147483647:select TID, TNAME from TESTMYBATIS where TID = ?:6=[TestMybatis [tid=6, tname=asd]] [service] 2016-08-31 21:12:33,477 - com.erp.dao.TestMybatisMapper -23630 [http-nio-8080-exec-10] DEBUG com.erp.dao.TestMybatisMapper - Cache Hit Ratio [com.erp.dao.TestMybatisMapper]: 1.0 [service] 2016-08-31 21:12:33,477 - org.mybatis.spring.SqlSessionUtils -23630 [http-nio-8080-exec-10] DEBUG org.mybatis.spring.SqlSessionUtils - Closing non transactional SqlSession [[email protected]] TestMybatis [tid=6, tname=asd] [service] 2016-08-31 21:12:33,482 - org.springframework.web.servlet.DispatcherServlet -23635 [http-nio-8080-exec-10] DEBUG org.springframework.web.servlet.DispatcherServlet - Null ModelAndView returned to DispatcherServlet with name 'springMVC': assuming HandlerAdapter completed request handling [service] 2016-08-31 21:12:33,482 - org.springframework.web.servlet.DispatcherServlet -23635 [http-nio-8080-exec-10] DEBUG org.springframework.web.servlet.DispatcherServlet - Successfully completed request

兩次都是查詢資料庫裡的資料,只不過第一次在查詢之前我們先插入了一條資料,更新了快取,

其實這並不能發揮redis的優勢,更多的redis作為二級快取伺服器使用,實現我們自定義的二級快取,如何利用號redis實現更加的靈活的實現資料的同步才是最重要的

 

package com.erp.controller;

import java.math.BigDecimal;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.erp.dao.TestMybatisMapper;
import com.erp.model.TestMybatis;

@RestController
public class BaseController {

    @Autowired
    private TestMybatisMapper testMybatisMapper;

    @RequestMapping("s")
    public void test() {
        TestMybatis test = new TestMybatis();
        BigDecimal b = new BigDecimal("6");
        // test.setTid(b);
        // test.setTname("asd");
        // this.testMybatisMapper.insert(test);
        TestMybatis testMybatis = this.testMybatisMapper.selectByPrimaryKey(b);
        System.out.println(testMybatis.toString());
    }

}

這裡我們需要注意一下我們好像不能使用junit和spring的那個test測試類,因為我們在那個好像每次都是從新載入的配置檔案導致了每次都是重啟的伺服器一樣

package com.erp.model;

import java.io.Serializable;
import java.math.BigDecimal;

public class TestMybatis implements Serializable{
    /**
     * 
     */
    private static final long serialVersionUID = 1L;

    private BigDecimal tid;

    private String tname;

    public BigDecimal getTid() {
        return tid;
    }

    public void setTid(BigDecimal tid) {
        this.tid = tid;
    }

    public String getTname() {
        return tname;
    }

    public void setTname(String tname) {
        this.tname = tname == null ? null : tname.trim();
    }

    @Override
    public String toString() {
        return "TestMybatis [tid=" + tid + ", tname=" + tname + "]";
    }

}
<cache type="com.erp.utils.redcache.LoggingRedisCache"/>
package com.erp.utils.redcache;

import org.apache.ibatis.cache.decorators.LoggingCache;

public class LoggingRedisCache extends LoggingCache {

    public LoggingRedisCache(String id) {
        super(new RedisCache(id));
    }

}
package com.erp.utils.redcache;

import org.junit.Test;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

public class PoolResource {

    private static String ADDRESS = "localhost";
    private static int PORT = 6379;
    private static String PASSWORD = "wang";
    // 可用連線最大數目
    // -1 表示不限制
    private static int MAX_ACTIVE = 1024;
    // 控制一個pool最多有多少個空閒的jedis例項,預設是8
    private static int MAX_JEDIS = 200;

    // 等待的可用連線的最大時間,單位毫秒,預設值為-1,表示永不超時,如果等待超時時間
    // 則丟擲JedisConnectionException
    // redis.clients.jedis.exceptions.JedisConnectionException: Could not get a
    // resource from the pool
    private static int MAX_WAIT = 10000;
    private static int TIMROUT = 10000;

    // 在borrow一個jedis例項時,是否提前進行validate操作:true ,得到的jedis例項是可用的;
    private static boolean TEST_ON_BORROW = true;
    private static JedisPool jedisPool = null;

    /**
     * 初始化連線池
     */
    static {
        JedisPoolConfig config = new JedisPoolConfig();
        //設定最大的連線數目,注意版本不同方法會有不同
        config.setMaxTotal(MAX_ACTIVE);
        config.setMaxIdle(MAX_JEDIS);
        config.setMaxWaitMillis(MAX_WAIT);
        config.setTestOnBorrow(TEST_ON_BORROW);
        jedisPool = new JedisPool(config, ADDRESS, PORT, TIMROUT, PASSWORD);
    }

    /**
     * 獲取Jedis例項
     * 
     * @return
     */
    // synchronized是Java中的關鍵字,是一種同步鎖。它修飾的物件有以下幾種:
    // 1. 修飾一個程式碼塊,被修飾的程式碼塊稱為同步語句塊,其作用的範圍是大括號{}括起來的程式碼,作用的物件是呼叫這個程式碼塊的物件;
    // 2. 修飾一個方法,被修飾的方法稱為同步方法,其作用的範圍是整個方法,作用的物件是呼叫這個方法的物件;
    // 3. 修改一個靜態的方法,其作用的範圍是整個靜態方法,作用的物件是這個類的所有物件;
    // 4. 修改一個類,其作用的範圍是synchronized後面括號括起來的部分,作用主的物件是這個類的所有物件。
    // 當兩個併發執行緒訪問同一個物件object中的這個synchronized(this)同步程式碼塊時,一個時間內只能有一個執行緒得到執行。另一個執行緒必須等待當前執行緒執行完這個程式碼塊以後才能執行該程式碼塊。

    public synchronized static Jedis getJedis() {
        try {
            if (jedisPool != null) {
                Jedis resource = jedisPool.getResource();
                return resource;
            } else {
                return null;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 釋放jedis資源
     * 
     * @param jedis
     */
    public static void returnResource(final Jedis jedis) {
        // if (jedis != null) {
        // jedisPool.returnResource(jedis);
        // }
        if (jedis != null) {
            jedis.close();
        }
    }

    @Test
    public void testConnect() {
        for (int i = 0; i < 100; i++) {
            Jedis jedis = getJedis();
            System.out.println("Connect");
        }
    }
}
package com.erp.utils.redcache;

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

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.ibatis.cache.Cache;

import redis.clients.jedis.Jedis;

/**
 * 繼承cache介面使用redis自定義實現mybatis的快取技術
 * 
 * @author Administrator
 *
 */
public class RedisCache implements Cache {
    private static Log logger = LogFactory.getLog(RedisCache.class);
    private Jedis redisClient = createClient();
    /** The ReadWriteLock.讀寫鎖 */
    private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();

    private String id;

    public RedisCache(final String id) {
        if (id == null) {
            throw new IllegalArgumentException("Cache instances require an ID");
        }
        logger.debug(">>>>>>>>>>>>>>>>>>>>>>>>RedisCache:id=" + id);
        this.id = id;
    }

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

    public int getSize() {
        return Integer.valueOf(redisClient.dbSize().toString());
    }

    public void putObject(Object key, Object value) {
        logger.debug(">>>>>>>>>>>>>>>>>>>>>>>>putObject:" + key + "=" + value);
        redisClient.set(SerializeUtil.serialize(key.toString()), SerializeUtil.serialize(value));
    }

    public Object getObject(Object key) {
        Object value = SerializeUtil.unserialize(redisClient.get(SerializeUtil.serialize(key.toString())));
        logger.debug(">>>>>>>>>>>>>>>>>>>>>>>>getObject:" + key + "=" + value);
        return value;
    }

    public Object removeObject(Object key) {
        return redisClient.expire(SerializeUtil.serialize(key.toString()), 0);
    }

    public void clear() {
        redisClient.flushDB();
    }

    public ReadWriteLock getReadWriteLock() {
        return readWriteLock;
    }

    protected static Jedis createClient() {
        try {
            //可以使用預設的config
            //JedisPool pool = new JedisPool(new JedisPoolConfig(), "localhost");
            return PoolResource.getJedis();
        } catch (Exception e) {
            e.printStackTrace();
        }
        throw new RuntimeException("初始化連線池錯誤");
    }

}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <settings>
        <!-- 這個配置使全域性的對映器啟用或禁用快取 -->
        <setting name="cacheEnabled" value="true" />
        <!-- 對於未知的SQL查詢,允許返回不同的結果集以達到通用的效果 -->
        <setting name="multipleResultSetsEnabled" value="true" />
        <!-- 配置預設的執行器。SIMPLE 執行器沒有什麼特別之處。REUSE 執行器重用預處理語句。BATCH 執行器重用語句和批量更新 -->
        <setting name="defaultExecutorType" value="REUSE" />
        <!-- 全域性啟用或禁用延遲載入。當禁用時,所有關聯物件都會即時載入。 -->
        <setting name="lazyLoadingEnabled" value="false" />
        <setting name="aggressiveLazyLoading" value="true" />
        <!-- <setting name="enhancementEnabled" value="true"/> -->
        <!-- 設定超時時間,它決定驅動等待一個數據庫響應的時間。 -->
        <setting name="defaultStatementTimeout" value="25000" />
    </settings>
</configuration>
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop" 
    xmlns:cache="http://www.springframework.org/schema/cache"  
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans  
                        http://www.springframework.org/schema/beans/spring-beans-3.1.xsd  
                        http://www.springframework.org/schema/context  
                        http://www.springframework.org/schema/context/spring-context-3.1.xsd  
                        http://www.springframework.org/schema/tx
                        http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
                        http://www.springframework.org/schema/aop 
                        http://www.springframework.org/schema/aop/spring-aop-3.1.xsd  
                        http://www.springframework.org/schema/cache 
                        http://www.springframework.org/schema/cache/spring-cache-3.1.xsd">
    <!-- 自動掃描 -->
    <context:component-scan base-package="com" />   
    <aop:aspectj-autoproxy proxy-target-class="true" />

    <!-- 引入配置檔案 -->
    <bean id="propertyConfigurer"
        class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="location" value="classpath:jdbc.properties" />
    </bean>

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
        destroy-method="close">
        <property name="driverClassName" value="${driver}" />
        <property name="url" value="${url}" />
        <property name="username" value="${username}" />
        <property name="password" value="${password}" />
        <!-- 初始化連線大小 -->
        <property name="initialSize" value="${initialSize}"></property>
        <!-- 連線池最大數量 -->
        <property name="maxActive" value="${maxActive}"></property>
        <!-- 連線池最大空閒 -->
        <property name="maxIdle" value="${maxIdle}"></property>
        <!-- 連線池最小空閒 -->
        <property name="minIdle" value="${minIdle}"></property>
        <!-- 獲取連線最大等待時間 -->
        <property name="maxWait" value="${maxWait}"></property>
    </bean>

    <!-- spring和MyBatis完美整合,不需要mybatis的配置對映檔案 -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="mapperLocations" value="classpath:com/erp/mapping/*.xml"/>
        <property name="configLocation" value="classpath:mybatis-config.xml" />
    </bean>

    <!-- DAO介面所在包名(sql對映類所對應的方法介面所在的位置),Spring會自動查詢其下的類 -->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.erp.dao" />
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
    </bean>

    <!-- (事務管理)transaction manager, use JtaTransactionManager for global tx -->
    <bean id="transactionManager"
        class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource" />
    </bean>

    <!--通過註解管理事物@Transactional -->
    <tx:annotation-driven transaction-manager="transactionManager" />

</beans>
<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>jdu</groupId>
    <artifactId>mybatisRedis</artifactId>
    <packaging>war</packaging>
    <version>0.0.1-SNAPSHOT</version>
    <name>mybatisRedis Maven Webapp</name>
    <url>http://maven.apache.org</url>
    <properties>
        <!-- spring版本號 -->
        <spring.version>4.0.2.RELEASE</spring.version>
        <!-- mybatis版本號 -->
        <mybatis.version>3.2.6</mybatis.version>
        <!-- log4j日誌檔案管理包版本 -->
        <slf4j.version>1.7.7</slf4j.version>
        <log4j.version>1.2.17</log4j.version>
    </properties>

    <dependencies>
        <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>
        <!-- 使用Spring的aop時需要使用到aspectjweaver包,所以需要新增aspectjweaver包 -->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>1.8.2</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.8.4</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>
            <!-- 表示開發的時候引入,釋出的時候不會載入此包 -->
            <scope>test</scope>
        </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>

        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>2.6.2</version>
        </dependency>
        <!-- 匯入java ee jar 包 -->
        <dependency>
            <groupId>javax</groupId>
            <artifactId>javaee-api</artifactId>
            <version>7.0</version>
        </dependency>
        <!-- D:\wanglihu\apacemaven\changku\oracle\ojdbc14\14\ojdbc14-14.jar -->
        <dependency>
            <groupId>oracle</groupId>
            <artifactId>ojdbc14</artifactId>
            <version>14</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>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>

        <!--新增json包 -->
        <dependency>
            <groupId>net.sf.json-lib</groupId>
            <artifactId>json-lib</artifactId>
            <version>2.2.3</version>
            <classifier>jdk15</classifier>
        </dependency>

    </dependencies>
    <build>
        <finalName>mybatisRedis</finalName>
    </build>
</project>

最後附上幾個連結

http://www.tuicool.com/articles/quqmy2

 

http://blog.csdn.net/yjl33/article/details/50401211

 

這個也不錯

http://www.cnblogs.com/wcyBlog/p/4402567.html