美文网首页Mybatis Java学习笔记程序员
Spring Boot + Mybatis + Ehcache

Spring Boot + Mybatis + Ehcache

作者: xiaolyuh | 来源:发表于2017-06-29 14:55 被阅读2139次

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

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

    application.properties开启mybatis中二级缓存

    ==mybatis.configuration.cache-enabled=true==

    默认二级缓存是开启的

    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
    
    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-ehcache</artifactId>
        <packaging>jar</packaging>
    
        <name>spring-boot-student-mybatis-ehcache</name>
        <description>Demo Mybatis ehcache 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>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>net.sf.ehcache</groupId>
                <artifactId>ehcache</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.mybatis</groupId>
                <artifactId>mybatis-ehcache</artifactId>
                <version>1.0.0</version>
            </dependency>
        </dependencies>
    
    </project>
    
    

    Ehcache配置

    在src\main\resources目录下创建ehcache.xml文件,内容如下:

    <?xml version="1.0" encoding="UTF-8"?>
    <ehcache>
    
        <!--
            http://www.cnblogs.com/lzy1991/p/5335249.html
            http://www.cnblogs.com/little-fly/p/6251439.html
            缓存配置
               diskStore:指定数据在磁盘中的存储位置。
               name:缓存名称。
               defaultCache:当借助CacheManager.add("demoCache")创建Cache时,EhCache便会采用<defalutCache/>指定的的管理策略,以下属性是必须的:
               maxElementsInMemory:缓存最大个数。
               eternal:对象是否永久有效,一但设置了,timeout将不起作用。
               timeToIdleSeconds:设置对象在失效前的允许闲置时间(单位:秒)。仅当eternal=false对象不是永久有效时使用,可选属性,默认值是0,也就是可闲置时间无穷大。
               timeToLiveSeconds:设置对象在失效前允许存活时间(单位:秒)。最大时间介于创建时间和失效时间之间。仅当eternal=false对象不是永久有效时使用,默认是0.,也就是对象存活时间无穷大。
               overflowToDisk:当内存中对象数量达到maxElementsInMemory时,Ehcache将会对象写到磁盘中。
               diskSpoolBufferSizeMB:这个参数设置DiskStore(磁盘缓存)的缓存区大小。默认是30MB。每个Cache都应该有自己的一个缓冲区。
               maxElementsOnDisk:硬盘最大缓存个数。
               diskPersistent:是否缓存虚拟机重启期数据 Whether the disk store persists between restarts of the Virtual Machine. The default value is false.
               diskExpiryThreadIntervalSeconds:磁盘失效线程运行时间间隔,默认是120秒。
               memoryStoreEvictionPolicy:当达到maxElementsInMemory限制时,Ehcache将会根据指定的策略去清理内存。默认策略是LRU(最近最少使用)。你可以设置为FIFO(先进先出)或是LFU(较少使用)。
               clearOnFlush:内存数量最大时是否清除。
        -->
        <diskStore path="e:\ehcache" />
        <defaultCache
                maxElementsInMemory="10000"
                eternal="false"
                timeToIdleSeconds="120"
                timeToLiveSeconds="120"
                overflowToDisk="true"
                maxElementsOnDisk="10000000"
                diskPersistent="false"
                diskExpiryThreadIntervalSeconds="120"
                memoryStoreEvictionPolicy="LRU"
        />
    </ehcache>
    

    Mapper文件

    <cache /> 添加这个节点会默认将该namespace下所有的的select语句缓存。如果不需要进行缓存,需要设置useCache="false"。

     <select id="findByPage" resultMap="BaseResultMap" useCache="false">
    

    完整的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">
        <!--mybatis ehcache缓存配置 -->
        <!-- 以下两个<cache>标签二选一,第一个可以输出日志,第二个不输出日志 -->
        <!--<cache type="org.mybatis.caches.ehcache.LoggingEhcache" />
        <cache type="org.mybatis.caches.ehcache.EhcacheCache"/>-->
    
        <!--根据需求调整缓存参数:-->
        <cache type="org.mybatis.caches.ehcache.EhcacheCache">
            <property name="timeToIdleSeconds" value="3600"/>
            <property name="timeToLiveSeconds" value="3600"/>
            <!-- 同ehcache参数maxElementsInMemory -->
            <property name="maxEntriesLocalHeap" value="1000"/>
            <!-- 同ehcache参数maxElementsOnDisk -->
            <property name="maxEntriesLocalDisk" value="10000000"/>
            <property name="memoryStoreEvictionPolicy" value="LRU"/>
        </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>
    

    实体类

    package com.xiaolyuh.domain.model;
    
    import java.io.Serializable;
    
    public class Person implements Serializable {
    
        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;
        }
    }
    

    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();
    }
    

    Severice接口类

    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);
    }
    
    

    Severice实现类

    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.github.pagehelper.Page;
    import com.xiaolyuh.domain.model.Person;
    import com.xiaolyuh.service.PersonService;
    import org.junit.Assert;
    import org.junit.Before;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import com.alibaba.fastjson.JSON;
    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.test.context.junit4.SpringRunner;
    
    import java.util.List;
    
    @RunWith(SpringRunner.class)
    @SpringBootTest
    public class PersonMapperTests {
    
        private Logger logger = LoggerFactory.getLogger(PersonMapperTests.class);
    
        @Autowired
        private PersonService personService;
    
        @Before
        public void testInsert() {
            Person 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));
        }
    
        @Test
        public void testCacheByPage() {
            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(persons.toString());
            logger.debug(JSON.toJSONString(persons));
        }
    
    }
    
    

    执行测试类,打印日志信息

     Cache Hit Ratio [com.xiaolyuh.domain.mapper.PersonMapper]: 0.5
    2017-06-28 10:15:32.214 DEBUG 10472 --- [           main] org.mybatis.spring.SqlSessionUtils       : Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@3f6c2763]
    2017-06-28 10:15:32.214 DEBUG 10472 --- [           main] org.mybatis.spring.SqlSessionUtils       : Transaction synchronization committing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@3f6c2763]
    2017-06-28 10:15:32.214 DEBUG 10472 --- [           main] org.mybatis.spring.SqlSessionUtils       : Transaction synchronization deregistering SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@3f6c2763]
    2017-06-28 10:15:32.214 DEBUG 10472 --- [           main] org.mybatis.spring.SqlSessionUtils       : Transaction synchronization closing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@3f6c2763]
    2017-06-28 10:15:32.223 DEBUG 10472 --- [           main] com.xiaolyuh.PersonMapperTests           : 第一次请求时间:26ms
    2017-06-28 10:15:32.223 DEBUG 10472 --- [           main] com.xiaolyuh.PersonMapperTests           : 第二次请求时间:11ms
    
    

    源码

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

    spring-boot-student-mybatis-ehcache工程


    扫码有红包哦

    相关文章

      网友评论

        本文标题:Spring Boot + Mybatis + Ehcache

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