美文网首页spring-bootJava 杂谈Java学习笔记
Spring Boot + Mybatis + Redis二级缓

Spring Boot + Mybatis + Redis二级缓

作者: xiaolyuh | 来源:发表于2017-06-29 15:29 被阅读1171次

    二级缓存是多个SqlSession共享的,其作用域是mapper的同一个namespace,不同的sqlSession两次执行相同namespace下的sql语句且向sql中传递参数也相同即最终执行相同的sql语句,第一次执行完毕会将数据库中查询的数据写到缓存(内存),第二次会从缓存中获取数据将不再从数据库查询,从而提高查询效率。Mybatis默认没有开启二级缓存需要在setting全局参数中配置开启二级缓存。

    下面是使用Redis来作为Mybatis二级缓存的实例:

    Redis的安装使用的是Docker,Docker的简介

    application.properties

    在application.properties文件中配置Redis,Mybatis,开启Mybatis二级缓存等:

    server.port=80
    # 数据源配置
    spring.datasource.url=jdbc:mysql://localhost:3306/ssb_test
    spring.datasource.driver-class-name=com.mysql.jdbc.Driver
    spring.datasource.username=root
    spring.datasource.password=root
    #连接池配置
    #spring.datasource.type=org.apache.commons.dbcp2.BasicDataSource
    
    #mybatis
    #entity扫描的包名
    mybatis.type-aliases-package=com.xiaolyuh.domain.model
    #Mapper.xml所在的位置
    mybatis.mapper-locations=classpath*:/mybaits/*Mapper.xml
    #开启MyBatis的二级缓存
    mybatis.configuration.cache-enabled=true
    
    #pagehelper
    pagehelper.helperDialect=mysql
    pagehelper.reasonable=true
    pagehelper.supportMethodsArguments=true
    pagehelper.params=count=countSql
    
    #日志配置
    logging.level.com.xiaolyuh=debug
    logging.level.org.springframework.web=debug
    logging.level.org.springframework.transaction=debug
    logging.level.org.mybatis=debug
    
    #redis
    #database name
    spring.redis.database=0
    #server host
    spring.redis.host=192.168.195.128
    #server password
    spring.redis.password=
    #connection port
    spring.redis.port=6378
    #spring.redis.pool.max-idle=8 # pool settings ...
    #spring.redis.pool.min-idle=0
    #spring.redis.pool.max-active=8
    #spring.redis.pool.max-wait=-1
    #spring.redis.sentinel.master= # name of Redis server
    #spring.redis.sentinel.nodes= # comma-separated list of host:port pairs
    
    debug=false
    

    pom.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <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/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
    
        <artifactId>spring-boot-student-mybatis-redis</artifactId>
        <packaging>jar</packaging>
    
        <name>spring-boot-student-mybatis-redis</name>
        <description>Demo Mybatis Redis for Spring Boot</description>
    
        <parent>
            <groupId>com.xiaolyuh</groupId>
            <artifactId>spring-boot-student</artifactId>
            <version>0.0.1-SNAPSHOT</version>
            <relativePath />
        </parent>
    
        <properties>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
            <java.version>1.8</java.version>
        </properties>
    
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-redis</artifactId>
            </dependency>
    
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
                <version>1.3.0</version>
            </dependency>
            <!--pagehelper -->
            <dependency>
                <groupId>com.github.pagehelper</groupId>
                <artifactId>pagehelper-spring-boot-starter</artifactId>
                <version>1.1.1</version>
            </dependency>
    
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>fastjson</artifactId>
                <version>1.2.31</version>
            </dependency>
    
            <dependency>
                <groupId>org.mybatis</groupId>
                <artifactId>mybatis-ehcache</artifactId>
                <version>1.0.0</version>
            </dependency>
        </dependencies>
    
    </project>
    
    

    Redis配置类替换序列化实现方式

    package com.xiaolyuh.config;
    
    import com.fasterxml.jackson.annotation.JsonAutoDetect;
    import com.fasterxml.jackson.annotation.PropertyAccessor;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.data.redis.connection.RedisConnectionFactory;
    import org.springframework.data.redis.core.RedisTemplate;
    import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
    import org.springframework.data.redis.serializer.StringRedisSerializer;
    
    @Configuration
    public class RedisConfig {
    
        /**
         * 重写Redis序列化方式,使用Json方式:
         * 当我们的数据存储到Redis的时候,我们的键(key)和值(value)都是通过Spring提供的Serializer序列化到数据库的。RedisTemplate默认使用的是JdkSerializationRedisSerializer,StringRedisTemplate默认使用的是StringRedisSerializer。
         * Spring Data JPA为我们提供了下面的Serializer:
         * GenericToStringSerializer、Jackson2JsonRedisSerializer、JacksonJsonRedisSerializer、JdkSerializationRedisSerializer、OxmSerializer、StringRedisSerializer。
         * 在此我们将自己配置RedisTemplate并定义Serializer。
         * @param redisConnectionFactory
         * @return
         */
        @Bean
        public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
            RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
            redisTemplate.setConnectionFactory(redisConnectionFactory);
    
            Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<Object>(Object.class);
            ObjectMapper om = new ObjectMapper();
            om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
            om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);  
            jackson2JsonRedisSerializer.setObjectMapper(om);
    
            // 设置值(value)的序列化采用Jackson2JsonRedisSerializer。
            redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
            // 设置键(key)的序列化采用StringRedisSerializer。
            redisTemplate.setKeySerializer(new StringRedisSerializer());
    
            redisTemplate.afterPropertiesSet();
            return redisTemplate;
        }
    }
    

    Spring容器获取Bean工具类

    通过Spring Aware(容器感知)来获取到ApplicationContext,然后根据ApplicationContext获取容器中的Bean。

    package com.xiaolyuh.holder;
    
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.ApplicationContextAware;
    import org.springframework.stereotype.Component;
    
    /**
     * 以静态变量保存Spring ApplicationContext, 可在任何代码任何地方任何时候中取出ApplicaitonContext.
     */
    @Component
    public class SpringContextHolder implements ApplicationContextAware {
        private static ApplicationContext applicationContext;
    
        /**
         * 实现ApplicationContextAware接口的context注入函数, 将其存入静态变量.
         */
        public void setApplicationContext(ApplicationContext applicationContext) {
            SpringContextHolder.applicationContext = applicationContext; // NOSONAR
        }
    
        /**
         * 取得存储在静态变量中的ApplicationContext.
         */
        public static ApplicationContext getApplicationContext() {
            checkApplicationContext();
            return applicationContext;
        }
    
        /**
         * 从静态变量ApplicationContext中取得Bean, 自动转型为所赋值对象的类型.
         */
        @SuppressWarnings("unchecked")
        public static <T> T getBean(String name) {
            checkApplicationContext();
            return (T) applicationContext.getBean(name);
        }
    
        /**
         * 从静态变量ApplicationContext中取得Bean, 自动转型为所赋值对象的类型.
         */
        @SuppressWarnings("unchecked")
        public static <T> T getBean(Class<T> clazz) {
            checkApplicationContext();
            return (T) applicationContext.getBeansOfType(clazz);
        }
    
        /**
         * 清除applicationContext静态变量.
         */
        public static void cleanApplicationContext() {
            applicationContext = null;
        }
    
        private static void checkApplicationContext() {
            if (applicationContext == null) {
                throw new IllegalStateException("applicaitonContext未注入,请在applicationContext.xml中定义SpringContextHolder");
            }
        }
    }
    

    自定的Mybatis缓存

    自定义缓存需要实现Mybatis的Cache接口,我这里将使用Redis来作为缓存的容器。

    package com.xiaolyuh.cache;
    
    import com.xiaolyuh.holder.SpringContextHolder;
    import org.apache.ibatis.cache.Cache;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.dao.DataAccessException;
    import org.springframework.data.redis.connection.RedisConnection;
    import org.springframework.data.redis.core.RedisCallback;
    import org.springframework.data.redis.core.RedisTemplate;
    import org.springframework.util.CollectionUtils;
    
    import java.util.Collections;
    import java.util.Set;
    import java.util.concurrent.TimeUnit;
    import java.util.concurrent.locks.ReadWriteLock;
    import java.util.concurrent.locks.ReentrantReadWriteLock;
    
    /**
     * 使用Redis来做Mybatis的二级缓存
     * 实现Mybatis的Cache接口
     */
    public class MybatisRedisCache implements Cache {
    
        private static final Logger logger = LoggerFactory.getLogger(MybatisRedisCache.class);
    
        // 读写锁
        private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock(true);
    
        private RedisTemplate<String, Object> redisTemplate = SpringContextHolder.getBean("redisTemplate");
    
        private String id;
    
        public MybatisRedisCache(final String id) {
            if (id == null) {
                throw new IllegalArgumentException("Cache instances require an ID");
            }
            logger.info("Redis Cache id " + id);
            this.id = id;
        }
    
        @Override
        public String getId() {
            return this.id;
        }
    
        @Override
        public void putObject(Object key, Object value) {
            if (value != null) {
                // 向Redis中添加数据,有效时间是2天
                redisTemplate.opsForValue().set(key.toString(), value, 2, TimeUnit.DAYS);
            }
        }
    
        @Override
        public Object getObject(Object key) {
            try {
                if (key != null) {
                    Object obj = redisTemplate.opsForValue().get(key.toString());
                    return obj;
                }
            } catch (Exception e) {
                logger.error("redis ");
            }
            return null;
        }
    
        @Override
        public Object removeObject(Object key) {
            try {
                if (key != null) {
                    redisTemplate.delete(key.toString());
                }
            } catch (Exception e) {
            }
            return null;
        }
    
        @Override
        public void clear() {
            logger.debug("清空缓存");
            try {
                Set<String> keys = redisTemplate.keys("*:" + this.id + "*");
                if (!CollectionUtils.isEmpty(keys)) {
                    redisTemplate.delete(keys);
                }
            } catch (Exception e) {
            }
        }
    
        @Override
        public int getSize() {
            Long size = (Long) redisTemplate.execute(new RedisCallback<Long>() {
                @Override
                public Long doInRedis(RedisConnection connection) throws DataAccessException {
                    return connection.dbSize();
                }
            });
            return size.intValue();
        }
    
        @Override
        public ReadWriteLock getReadWriteLock() {
            return this.readWriteLock;
        }
    }
    
    

    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.xiaolyuh.domain.mapper.PersonMapper">
    
        <cache type="com.xiaolyuh.cache.MybatisRedisCache">
            <property name="eviction" value="LRU" />
            <property name="flushInterval" value="6000000" />
            <property name="size" value="1024" />
            <property name="readOnly" value="false" />
        </cache>
    
        <resultMap id="BaseResultMap" type="com.xiaolyuh.domain.model.Person">
            <!--
              WARNING - @mbggenerated
              This element is automatically generated by MyBatis Generator, do not modify.
            -->
            <id column="id" property="id" jdbcType="BIGINT"/>
            <result column="name" property="name" jdbcType="VARCHAR"/>
            <result column="age" property="age" jdbcType="INTEGER"/>
            <result column="address" property="address" jdbcType="VARCHAR"/>
        </resultMap>
        <sql id="Base_Column_List">
            <!--
              WARNING - @mbggenerated
              This element is automatically generated by MyBatis Generator, do not modify.
            -->
            id, name, age, address
        </sql>
        <select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.Long">
            <!--
              WARNING - @mbggenerated
              This element is automatically generated by MyBatis Generator, do not modify.
            -->
            select
            <include refid="Base_Column_List"/>
            from person
            where id = #{id,jdbcType=BIGINT}
        </select>
        <delete id="deleteByPrimaryKey" parameterType="java.lang.Long">
            <!--
              WARNING - @mbggenerated
              This element is automatically generated by MyBatis Generator, do not modify.
            -->
            delete from person
            where id = #{id,jdbcType=BIGINT}
        </delete>
        <insert id="insert" parameterType="com.xiaolyuh.domain.model.Person">
            <!--
              WARNING - @mbggenerated
              This element is automatically generated by MyBatis Generator, do not modify.
            -->
            <selectKey resultType="java.lang.Long" keyProperty="id" order="AFTER">
                SELECT LAST_INSERT_ID()
            </selectKey>
            insert into person (name, age, address
            )
            values (#{name,jdbcType=VARCHAR}, #{age,jdbcType=INTEGER}, #{address,jdbcType=VARCHAR}
            )
        </insert>
        <insert id="insertSelective" parameterType="com.xiaolyuh.domain.model.Person">
            <!--
              WARNING - @mbggenerated
              This element is automatically generated by MyBatis Generator, do not modify.
            -->
            <selectKey resultType="java.lang.Long" keyProperty="id" order="AFTER">
                SELECT LAST_INSERT_ID()
            </selectKey>
            insert into person
            <trim prefix="(" suffix=")" suffixOverrides=",">
                <if test="name != null">
                    name,
                </if>
                <if test="age != null">
                    age,
                </if>
                <if test="address != null">
                    address,
                </if>
            </trim>
            <trim prefix="values (" suffix=")" suffixOverrides=",">
                <if test="name != null">
                    #{name,jdbcType=VARCHAR},
                </if>
                <if test="age != null">
                    #{age,jdbcType=INTEGER},
                </if>
                <if test="address != null">
                    #{address,jdbcType=VARCHAR},
                </if>
            </trim>
        </insert>
        <update id="updateByPrimaryKeySelective" parameterType="com.xiaolyuh.domain.model.Person">
            <!--
              WARNING - @mbggenerated
              This element is automatically generated by MyBatis Generator, do not modify.
            -->
            update person
            <set>
                <if test="name != null">
                    name = #{name,jdbcType=VARCHAR},
                </if>
                <if test="age != null">
                    age = #{age,jdbcType=INTEGER},
                </if>
                <if test="address != null">
                    address = #{address,jdbcType=VARCHAR},
                </if>
            </set>
            where id = #{id,jdbcType=BIGINT}
        </update>
        <update id="updateByPrimaryKey" parameterType="com.xiaolyuh.domain.model.Person">
            <!--
              WARNING - @mbggenerated
              This element is automatically generated by MyBatis Generator, do not modify.
            -->
            update person
            set name = #{name,jdbcType=VARCHAR},
            age = #{age,jdbcType=INTEGER},
            address = #{address,jdbcType=VARCHAR}
            where id = #{id,jdbcType=BIGINT}
        </update>
    
        <!-- 对这个语句useCache="true"默认是true,可以不写 -->
        <select id="findAll" resultMap="BaseResultMap" useCache="true">
            select
            <include refid="Base_Column_List"/>
            from person
        </select>
    
        <!-- 对这个语句禁用二级缓存 -->
        <select id="findByPage" resultMap="BaseResultMap" useCache="false">
            select
            <include refid="Base_Column_List"/>
            from person
        </select>
    </mapper>
    

    Mapper接口

    package com.xiaolyuh.domain.mapper;
    
    import com.github.pagehelper.Page;
    import com.xiaolyuh.domain.model.Person;
    import org.apache.ibatis.annotations.Mapper;
    
    import java.util.List;
    
    @Mapper//声明成mybatis Dao层的Bean,也可以在配置类上使用@MapperScan("com.xiaolyuh.domain.mapper")注解声明
    public interface PersonMapper {
    
        int deleteByPrimaryKey(Long id);
    
        int insert(Person record);
    
        int insertSelective(Person record);
    
        Person selectByPrimaryKey(Long id);
    
        int updateByPrimaryKeySelective(Person record);
    
        int updateByPrimaryKey(Person record);
    
        /**
         * 获取所有数据
         * @return
         */
        List<Person> findAll();
    
        /**
         * 分页查询数据
         * @return
         */
        Page<Person> findByPage();
    }
    

    实体类

    package com.xiaolyuh.domain.model;
    
    import java.io.Serializable;
    
    public class Person implements Serializable {
    
        private static final long serialVersionUID = 1L;
    
        private Long id;
    
        /**
         * 名称
         */
        private String name;
    
        /**
         * 年龄
         */
        private Integer age;
    
        /**
         * 地址
         */
        private String address;
    
        public Long getId() {
            return id;
        }
    
        public void setId(Long id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public Integer getAge() {
            return age;
        }
    
        public void setAge(Integer age) {
            this.age = age;
        }
    
        public String getAddress() {
            return address;
        }
    
        public void setAddress(String address) {
            this.address = address;
        }
    
        @Override
        public String toString() {
            return "Person{" +
                    "id=" + id +
                    ", name='" + name + '\'' +
                    ", age=" + age +
                    ", address='" + address + '\'' +
                    '}';
        }
    }
    

    Service接口

    package com.xiaolyuh.service;
    
    import com.github.pagehelper.Page;
    import com.xiaolyuh.domain.model.Person;
    
    import java.util.List;
    
    /**
     * Created by yuhao.wang on 2017/6/19.
     */
    public interface PersonService {
    
        List<Person> findAll();
    
        /**
         * 分页查询
         * @param pageNo 页号
         * @param pageSize 每页显示记录数
         * @return
         */
        Page<Person> findByPage(int pageNo, int pageSize);
    
        void insert(Person person);
    }
    
    

    Service实现类

    package com.xiaolyuh.service.impl;
    
    import com.github.pagehelper.Page;
    import com.github.pagehelper.PageHelper;
    import com.xiaolyuh.domain.mapper.PersonMapper;
    import com.xiaolyuh.domain.model.Person;
    import com.xiaolyuh.service.PersonService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    import org.springframework.transaction.annotation.Transactional;
    
    import java.util.List;
    
    /**
     * Created by yuhao.wang on 2017/6/19.
     */
    @Service
    @Transactional(readOnly = true)
    public class PersonServiceImpl implements PersonService {
    
        @Autowired
        private PersonMapper personMapper;
    
        @Override
        public List<Person> findAll() {
            return personMapper.findAll();
        }
    
        @Override
        public Page<Person> findByPage(int pageNo, int pageSize) {
            PageHelper.startPage(pageNo, pageSize);
            return personMapper.findByPage();
        }
    
        @Override
        @Transactional
        public void insert(Person person) {
            personMapper.insert(person);
        }
    
    
    }
    
    

    测试类

    package com.xiaolyuh;
    
    import com.alibaba.fastjson.JSON;
    import com.github.pagehelper.Page;
    import com.xiaolyuh.domain.model.Person;
    import com.xiaolyuh.holder.SpringContextHolder;
    import com.xiaolyuh.service.PersonService;
    import org.junit.Assert;
    import org.junit.Before;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.data.redis.core.RedisTemplate;
    import org.springframework.test.context.junit4.SpringRunner;
    
    import java.util.ArrayList;
    import java.util.List;
    import java.util.concurrent.TimeUnit;
    
    @RunWith(SpringRunner.class)
    @SpringBootTest
    public class PersonMapperTests {
    
        private Logger logger = LoggerFactory.getLogger(PersonMapperTests.class);
    
        @Autowired
        private PersonService personService;
    
        @Autowired
        private RedisTemplate<String, Object> redisTemplate;
    
        Person person = null;
    
        @Before
        public void testInsert() {
            person = new Person();
            person.setName("测试");
            person.setAddress("address");
            person.setAge(10);
            personService.insert(person);
    
            Assert.assertNotNull(person.getId());
            logger.debug(JSON.toJSONString(person));
        }
    
        @Test
        public void testFindAll() {
            List<Person> persons = personService.findAll();
    
            Assert.assertNotNull(persons);
            logger.debug(JSON.toJSONString(persons));
        }
    
        @Test
        public void testFindByPage() {
            Page<Person> persons = personService.findByPage(1, 2);
    
            Assert.assertNotNull(persons);
            logger.debug(persons.toString());
            logger.debug(JSON.toJSONString(persons));
        }
    
        // 测试mybatis缓存
        @Test
        public void testCache() {
            long begin = System.currentTimeMillis();
            List<Person> persons = personService.findAll();
            long ing = System.currentTimeMillis();
            personService.findAll();
            long end = System.currentTimeMillis();
            logger.debug("第一次请求时间:" + (ing - begin) + "ms");
            logger.debug("第二次请求时间:" + (end - ing) + "ms");
    
            Assert.assertNotNull(persons);
            logger.debug(JSON.toJSONString(persons));
        }
    
        // 测试Redis存储和获取一个List
        @Test
        public void testRedisCacheSetList() {
            List<Person> persons = new ArrayList<>();
            persons.add(person);
            persons.add(person);
            persons.add(person);
            redisTemplate.opsForValue().set(person.getId() + "", persons, 2, TimeUnit.MINUTES);
            persons = (List<Person>) redisTemplate.opsForValue().get(person.getId() + "");
            System.out.println(JSON.toJSONString(persons));
        }
    
        // 测试Redis存储和获取一个Object
        @Test
        public void testRedisCacheSetObject() {
            redisTemplate.opsForValue().set(person.getId() + "", person, 2, TimeUnit.MINUTES);
            Object p = redisTemplate.opsForValue().get(person.getId() + "");
            if (p instanceof Person) {
                Person person1 = (Person) p;
                System.out.println(JSON.toJSONString(person1));
            }
        }
    
        // 测试 通过Spring Aware获取Spring容器中的额Bean
        @Test
        public void testApplicationContextAware() {
            RedisTemplate redisTemplate = SpringContextHolder.getBean("redisTemplate");
            System.out.println(redisTemplate);
        }
    
    }
    
    

    日志

    2017-06-29 15:22:22.351 DEBUG 12976 --- [           main] com.xiaolyuh.domain.mapper.PersonMapper  : Cache Hit Ratio [com.xiaolyuh.domain.mapper.PersonMapper]: 0.5
    2017-06-29 15:22:22.351 DEBUG 12976 --- [           main] org.mybatis.spring.SqlSessionUtils       : Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2b2a4332]
    2017-06-29 15:22:22.351 DEBUG 12976 --- [           main] org.mybatis.spring.SqlSessionUtils       : Transaction synchronization committing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2b2a4332]
    2017-06-29 15:22:22.351 DEBUG 12976 --- [           main] org.mybatis.spring.SqlSessionUtils       : Transaction synchronization deregistering SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2b2a4332]
    2017-06-29 15:22:22.351 DEBUG 12976 --- [           main] org.mybatis.spring.SqlSessionUtils       : Transaction synchronization closing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2b2a4332]
    2017-06-29 15:22:22.353 DEBUG 12976 --- [           main] com.xiaolyuh.PersonMapperTests           : 第一次请求时间:92ms
    2017-06-29 15:22:22.354 DEBUG 12976 --- [           main] com.xiaolyuh.PersonMapperTests           : 第二次请求时间:68ms
    

    源码

    https://github.com/wyh-spring-ecosystem-student/spring-boot-student/tree/releases

    spring-boot-student-mybatis-redis工程

    扫码有红包哦

    相关文章

      网友评论

      • 海之蓝_f2e3:请教下,我的运行一直报:applicaitonContext未注入,请在applicationContext.xml中定义SpringContextHolder是什么原因?
        海之蓝_f2e3:@xiaolyuh 主要我开始没在你这边看到有关xml配置和扫描的:smile:
        海之蓝_f2e3:@xiaolyuh 好吧,现在springboot都用properties或yml了,没用xml配置和扫描,所以我改成以下就可以了:
        private RedisTemplate<String, Object> redisTemplate;

        @Override
        public void putObject(Object key, Object value) {
        if (value != null) {
        getRedisTemplate();
        // 向Redis中添加数据,有效时间是2天
        redisTemplate.opsForValue().set(key.toString(), value, EXPIRE_TIME_IN_MINUTES, TimeUnit.DAYS);
        logger.debug("Put query result to redis");
        }
        }

        private void getRedisTemplate() {
        if (redisTemplate == null) {
        redisTemplate = ApplicationContextHolder.getBean("redisTemplate");
        }
        }
        xiaolyuh:这个需要配置成bean,你看一下你的包扫描是否扫描到这个类了

      本文标题:Spring Boot + Mybatis + Redis二级缓

      本文链接:https://www.haomeiwen.com/subject/vggmcxtx.html