Mybatis之缓存

来源:互联网 发布:公司数据库搭建 编辑:程序博客网 时间:2024/05/01 12:23

1.Mybatis的底层工作原理

此详细过程请看前博客 “Mybatis的工作原理”

2.测试缓存的环境准备

利用idea+maven+junit搭建一个项目,如果此步骤还不熟
请参照IDEA 之maven+junit构建。

然加入jdbc依赖 ,log4j2所需的依赖:

 <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->            <dependency>                <groupId>mysql</groupId>                <artifactId>mysql-connector-java</artifactId>                <version>5.1.38</version>            </dependency>            <!-- https://mvnrepository.com/artifact/com.oracle/ojdbc14 -->            <dependency>                <groupId>com.oracle</groupId>                <artifactId>ojdbc14</artifactId>                <version>10.2.0.3.0</version>            </dependency>            <!--添加log4j2依赖-->            <!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-core -->            <dependency>                <groupId>org.apache.logging.log4j</groupId>                <artifactId>log4j-core</artifactId>                <version>2.8.2</version>            </dependency>            <!-- https://mvnrepository.com/artifact/log4j/log4j -->            <dependency>                <groupId>log4j</groupId>                <artifactId>log4j</artifactId>                <version>1.2.17</version>            </dependency>            <!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-api -->            <dependency>                <groupId>org.apache.logging.log4j</groupId>                <artifactId>log4j-api</artifactId>                <version>2.8.2</version>            </dependency>            <!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-slf4j-impl -->            <dependency>                <groupId>org.apache.logging.log4j</groupId>                <artifactId>log4j-slf4j-impl</artifactId>                <version>2.8.2</version>            </dependency>            <!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-web -->            <dependency>                <groupId>org.apache.logging.log4j</groupId>                <artifactId>log4j-web</artifactId>                <version>2.8.2</version>            </dependency>

要看到mybatis的缓存就必须,通过日志来跟踪sql,所以还要整合log4j2。

log4j2的配置:

<?xml version="1.0" encoding="UTF-8"?><Configuration status="WARN">    <Appenders>        <!--输出的目的地-->        <Console name="Console" target="SYSTEM_OUT">            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %l %msg%n"/>        </Console>    </Appenders>    <Loggers>        <!--其他的日志以 error 为级别 ,除非有logger 覆盖 如下-->        <Root level="error">            <AppenderRef ref="Console"/>        </Root>        <!-- mapper结构所在的包-->        <Logger name="com.worldly.config.mapper" level="TRACE" additivity="false">            <AppenderRef ref="Console"/>        </Logger>    </Loggers></Configuration>  

用junit测试selectEmployeeList可以看到如下console输出,就说明环境已经准备好了。
这里写图片描述

3.Mybatis的缓存

3.1 mybatis的一级缓存SqlSession缓存

sqlSession缓存是默认开启的,在一个sqlSession在使用select的时候会先从本地缓存中读,如果没有才会连接数据库查询相关的数据,然后将查询的数据放入本地缓存,以便下次select。只要事务不提交( 增删该等动作)或者没有sqlSession.close(), 执行查询条件相同的第二次查询,就直接从缓存中取,不发sql。

 @Test    public void testCache1() {        InputStream resourceAsStream = ConfigTest.class.getResourceAsStream("../classes/mybatis-config.xml");        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);        SqlSession sqlSession = sqlSessionFactory.openSession();        //查询id为1的员工        Employee param = new Employee();        param.setId(1);        /**         * 1用sqlSession 获取mapper的代理对象 执行按条件查询,         * 由于是第一次查询,缓存中没有,会发出查询sql         */        EmployeeMapper mapper = sqlSession.getMapper(EmployeeMapper.class);        Employee employee = mapper.selectEmployeeByCondition(param);        System.out.println(employee);        /**         * 用同一sqlSession 获取mapper的代理对象 执行与1相同的查询         * 1查询后缓存中有数据,如果是相同的查询就直接从缓存中取,不发sql语句         */        EmployeeMapper mapper2 = sqlSession.getMapper(EmployeeMapper.class);        Employee employee2 = mapper2.selectEmployeeByCondition(param);        System.out.println(employee2);        //触发事务commit        sqlSession.commit();        /**         * 事务提交。本地缓存清空         * 虽然同sqlSession 执行为条件相同的查询,但还是要connection  db 进行select         */        EmployeeMapper mapper3 = sqlSession.getMapper(EmployeeMapper.class);        Employee employee3 = mapper3.selectEmployeeByCondition(param);        System.out.println(employee3);    }

这里写图片描述

3.2 mybatis的二级缓存Mapper级别的缓存

mybatis的二级缓存是namespace级别的,就是同一Mapper下的多个sqlSession共享一个缓存。因此只要有一个sqlSession发出了一个查询,第二sqlSession发出同样的查询的话,是直接从二级缓存中取数据的。
二级缓存默认不开启,如果要使用的话要在mybatis-config.xml的全局配置文件中开启,同时要在mapper 的sql映射文件中配置cache, 此外缓存的对象 必须 implments Serializable接口。

<!--配置缓存的全局开关 如果要使用缓存 就必须设置--><setting name="cacheEnabled" value="true"/><!--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.worldly.config.mapper.EmployeeMapper">    <!--开启缓存,如果不设置就默认使用mybatis自身的二级缓存-->    <cache/>    <resultMap id="empResultMap" type="com.worldly.config.entity.Employee">        <id column="emp_id" property="id"></id>        <result column="emp_name" property="name"/>        <result column="emp_email" property="email"/>        <result column="emp_tel" property="tel"/>        <result column="emp_dep" property="depId"/>    </resultMap>    <select id="selectEmployeeList" resultMap="empResultMap" databaseId="mysql">        select * from t_emp    </select>    <select id="selectEmployeeByCondition" resultMap="empResultMap" databaseId="mysql">        select * from t_emp WHERE emp_id=#{param.id}    </select></mapper>

我们用两个sqlSession去查询同一sql, 看是否会发出sql
测试代码:

 @Test    public void testCache2() {        InputStream resourceAsStream = ConfigTest.class.getResourceAsStream("../classes/mybatis-config.xml");        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);        SqlSession sqlSession = sqlSessionFactory.openSession();        //查询id为1的员工        Employee param = new Employee();        param.setId(1);        /**         * 1用sqlSession 获取mapper的代理对象 执行按条件查询,         * 由于是第一次查询,缓存中没有,会发出查询sql         */        EmployeeMapper mapper = sqlSession.getMapper(EmployeeMapper.class);        Employee employee = mapper.selectEmployeeByCondition(param);        System.out.println(employee);        //触发事务commit        sqlSession.commit();        /**         * 用同一sqlSession 获取mapper的代理对象 执行与1相同的查询         * 1查询后缓存中有数据,如果是相同的查询就直接从缓存中取,不发sql语句         */        SqlSession sqlSession2 = sqlSessionFactory.openSession();        EmployeeMapper mapper2 = sqlSession2.getMapper(EmployeeMapper.class);        Employee employee2 = mapper2.selectEmployeeByCondition(param);        System.out.println(employee2);    }

mybatis二级缓存测试输出

原创粉丝点击