SpringMVC + MyBatis + Mysql + Redis(做爲二級緩存)

1、添加redis所需依賴
pom.xmljava

<!--  使用redis做爲mysql緩存依賴開始-->
    <!-- spring-redis實現 -->
    <dependency>
      <groupId>org.springframework.data</groupId>
      <artifactId>spring-data-redis</artifactId>
      <version>1.6.2.RELEASE</version>
    </dependency>
    <!-- redis客戶端jar -->
    <dependency>
      <groupId>redis.clients</groupId>
      <artifactId>jedis</artifactId>
      <version>2.8.0</version>
    </dependency>

    <!--  使用redis做爲mysql緩存依賴結束-->

2、建立redis配置文件
redis.propertiesmysql

# Redis settings
redis.host=127.0.0.1
redis.port=6379
redis.pass=
redis.maxIdle=300
redis.maxActive=600
redis.maxWait=1000
redis.timeout=10000
redis.testOnBorrow=true

3、建立Mybatis緩存實現類MybatisRedisCacheredis

import org.apache.ibatis.cache.Cache;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.data.redis.connection.jedis.JedisConnection;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;
import redis.clients.jedis.exceptions.JedisConnectionException;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;


/**
 * @ClassName MybatisRedisCache
 * @Description: 使用redis做爲Mybatis第二級緩存 建立緩存實現類MybatisRedisCache
 * @Author Jason
 * @Date 2020/4/7  14:56
 * @Version V1.0
 **/

public class MybatisRedisCache implements Cache
{
    private static final Logger logger = LogManager.getLogger(MybatisRedisCache.class);

    private static JedisConnectionFactory jedisConnectionFactory;

    private final String id;

    /**
     * The {@code ReadWriteLock}.
     */
    private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();

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

    @Override
    public void clear()
    {
        JedisConnection connection = null;
        try
        {
            connection = jedisConnectionFactory.getConnection();
            connection.flushDb();
            connection.flushAll();
        }
        catch (JedisConnectionException e)
        {
            e.printStackTrace();
        }
        finally
        {
            if (connection != null) {
                connection.close();
            }
        }
    }

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

    @Override
    public Object getObject(Object key)
    {
        Object result = null;
        JedisConnection connection = null;
        try
        {
            connection = jedisConnectionFactory.getConnection();
            RedisSerializer<Object> serializer = new JdkSerializationRedisSerializer();
            result = serializer.deserialize(connection.get(serializer.serialize(key)));
        }
        catch (JedisConnectionException e)
        {
            e.printStackTrace();
        }
        finally
        {
            if (connection != null) {
                connection.close();
            }
        }
        return result;
    }

    @Override
    public ReadWriteLock getReadWriteLock()
    {
        return this.readWriteLock;
    }

    @Override
    public int getSize()
    {
        int result = 0;
        JedisConnection connection = null;
        try
        {
            connection = jedisConnectionFactory.getConnection();
            result = Integer.valueOf(connection.dbSize().toString());
        }
        catch (JedisConnectionException e)
        {
            e.printStackTrace();
        }
        finally
        {
            if (connection != null) {
                connection.close();
            }
        }
        return result;
    }

    @Override
    public void putObject(Object key, Object value)
    {
        JedisConnection connection = null;
        try
        {
            connection = jedisConnectionFactory.getConnection();
            RedisSerializer<Object> serializer = new JdkSerializationRedisSerializer();
            connection.set(serializer.serialize(key), serializer.serialize(value));
        }
        catch (JedisConnectionException e)
        {
            e.printStackTrace();
        }
        finally
        {
            if (connection != null) {
                connection.close();
            }
        }
    }

    @Override
    public Object removeObject(Object key)
    {
        JedisConnection connection = null;
        Object result = null;
        try
        {
            connection = jedisConnectionFactory.getConnection();
            RedisSerializer<Object> serializer = new JdkSerializationRedisSerializer();
            result =connection.expire(serializer.serialize(key), 0);
        }
        catch (JedisConnectionException e)
        {
            e.printStackTrace();
        }
        finally
        {
            if (connection != null) {
                connection.close();
            }
        }
        return result;
    }

    public static void setJedisConnectionFactory(JedisConnectionFactory jedisConnectionFactory) {
        MybatisRedisCache.jedisConnectionFactory = jedisConnectionFactory;
    }

}

4、建立緩存轉換中間類RedisCacheTransferspring

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;

/**
 * @ClassName RedisCacheTransfer
 * @Description: TODO 建立中間類RedisCacheTransfer,完成MybatisRedisCache.jedisConnectionFactory的靜態注入
 * @Author Jason
 * @Date 2020/4/7  15:40
 * @Version V1.0
 **/
public class RedisCacheTransfer {
    @Autowired
    public void setJedisConnectionFactory(JedisConnectionFactory jedisConnectionFactory) {
        MybatisRedisCache.setJedisConnectionFactory(jedisConnectionFactory);
    }
}

5、spring.xml 引入redis配置sql

<bean
            class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<!--        <property name="Location" value="classpath:jdbc.properties" />-->
        <property name="locations">
            <list>
                <value>classpath:jdbc.properties</value>
<!--                註冊redis配置文件-->
                <value>classpath:redis.properties</value>
            </list>
        </property>
    </bean>

<!-- redis數據源 -->
    <bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
        <property name="maxIdle" value="${redis.maxIdle}" />
        <property name="maxTotal" value="${redis.maxActive}" />
        <property name="maxWaitMillis" value="${redis.maxWait}" />
        <property name="testOnBorrow" value="${redis.testOnBorrow}" />
    </bean>
    <!-- Spring-redis鏈接池管理工廠 -->
    <bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
        <property name="poolConfig" ref="poolConfig" />
        <property name="port" value="${redis.port}" />
        <property name="hostName" value="${redis.host}"/>
        <property name="timeout" value="${redis.timeout}"/>
    </bean>


    <!-- 使用中間類解決RedisCache.jedisConnectionFactory的靜態注入,從而使MyBatis實現第三方緩存 -->
    <bean id="redisCacheTransfer" class="com.zqu.util.RedisCacheTransfer">
        <property name="jedisConnectionFactory" ref="jedisConnectionFactory"/>
    </bean>

6、mybatis配置緩存設置數據庫

<settings>

        <!-- 全局映射器啓用緩存 -->
        <setting name="cacheEnabled" value="true"/>

        <!-- 查詢時,關閉關聯對象即時加載以提升性能 -->
        <setting name="lazyLoadingEnabled" value="false"/>

        <!-- 對於未知的SQL查詢,容許返回不一樣的結果集以達到通用的效果 -->
        <setting name="multipleResultSetsEnabled" value="true"/>

        <!-- 容許使用列標籤代替列名 -->
        <setting name="useColumnLabel" value="true"/>

        <!-- 不容許使用自定義的主鍵值(好比由程序生成的UUID 32位編碼做爲鍵值),數據表的PK生成策略將被覆蓋 -->
        <setting name="useGeneratedKeys" value="false"/>

        <!-- 給予被嵌套的resultMap以字段-屬性的映射支持 FULL,PARTIAL -->
        <setting name="autoMappingBehavior" value="PARTIAL"/>

        <!-- 對於批量更新操做緩存SQL以提升性能 BATCH,SIMPLE -->
        <!-- <setting name="defaultExecutorType" value="BATCH" /> -->

        <!-- 數據庫超過25000秒仍未響應則超時 -->
        <!-- <setting name="defaultStatementTimeout" value="25000" /> -->

        <!-- Allows using RowBounds on nested statements -->
        <setting name="safeRowBoundsEnabled" value="false"/>

        <!-- Enables automatic mapping from classic database column names A_COLUMN to camel case classic Java property names aColumn. -->
        <setting name="mapUnderscoreToCamelCase" value="true"/>

        <!-- MyBatis uses local cache to prevent circular references and speed up repeated nested queries. By default (SESSION) all queries executed during a session are cached. If localCacheScope=STATEMENT
            local session will be used just for statement execution, no data will be shared between two different calls to the same SqlSession. -->
        <setting name="localCacheScope" value="SESSION"/>

        <!-- Specifies the JDBC type for null values when no specific JDBC type was provided for the parameter. Some drivers require specifying the column JDBC type but others work with generic values
            like NULL, VARCHAR or OTHER. -->
        <setting name="jdbcTypeForNull" value="OTHER"/>

        <!-- Specifies which Object's methods trigger a lazy load -->
        <setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/>

        <!-- 設置關聯對象加載的形態,此處爲按需加載字段(加載字段由SQL指 定),不會加載關聯表的全部字段,以提升性能 -->
        <setting name="aggressiveLazyLoading" value="true"/>

    </settings>

7、mapper中啓用二級緩存apache

<mapper namespace="com.zqu.dao.IEmployeesDao">
<!--    使用redis做爲二級緩存-->
    <cache type="com.zqu.util.MybatisRedisCache"/>
    ....
</mapper>

8、Mybatis的二級緩存redis已完成配置,測試Demo自行編寫
第一次測試結果!
未命中redis(即redis沒有相關數據)到mysql數據庫中查詢
image.png
第二次測試結果
因爲第一次已報查詢結果同步到redis,所以不須要再查詢mysql,查詢redis便可獲得數據
image.png緩存


參考:亡羊補牢丶session

相關文章
相關標籤/搜索