二级缓存:
- 它指的是 Mybatis 中 SqlSessionFactory 对象的缓存。由同一个 SqlSessionFactory 对象创建的 SqlSession 共享其缓存
- 二级缓存的使用步骤
- 让 Mybatis 框架支持二级缓存(在SqlMapConfig.xml配置)
- 让当前的映射文件支持二级缓存(在IUserDao.xml中配置)
- 让当前的操作支持二级缓存(在select标签中配置)
一、SqlMapConfig.xml
<?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> <properties resource="jdbcConfig.properties"/> <settings> <!--默认为 true--> <setting name="cacheEnabled" value="true"/> </settings> <typeAliases> <package name="domain"/> </typeAliases> <environments default="mysql"> <environment id="mysql"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="${driver}" /> <property name="url" value="${url}"/> <property name="username" value="${username}"/> <property name="password" value="${password}"/> </dataSource> </environment> </environments> <mappers> <package name="dao"/> </mappers> </configuration>
二、IUserDao.xml
<?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="dao.IUserDao"> <!--开启 uer 支持二级缓存--> <cache/> <!--不管有没有账户,用户的信息都得有,所以不能用内连接,所以用左外连接,会返回左表的所有数据--> <select id="findAll" resultType="user"> select *from user </select> <select id="findById" parameterType="integer" resultType="user" useCache="true"> select *from user where id=#{userId} </select> <update id="updateUser" parameterType="User"> update user set username=#{username},address=#{address} where id=#{id} </update> </mapper>
三、JAVA 代码
@Test public void testFirstLevelCache(){ SqlSession sqlSession1=factory.openSession(); IUserDao dao1=sqlSession1.getMapper(IUserDao.class); User user1=dao1.findById(1); System.out.println(user1); //一级缓存消失 sqlSession1.close(); SqlSession sqlSession2=factory.openSession(); IUserDao dao2=sqlSession2.getMapper(IUserDao.class); User user2=dao2.findById(1); System.out.println(user2); //一级缓存消失 sqlSession1.close(); System.out.println(user1==user2); }
四、Log 输出
Opening JDBC Connection [DEBUG] 2019-08-17 09:09:12,364 method:org.apache.ibatis.datasource.pooled.PooledDataSource.popConnection(PooledDataSource.java:424) Created connection 1634132079. [DEBUG] 2019-08-17 09:09:12,365 method:org.apache.ibatis.transaction.jdbc.JdbcTransaction.setDesiredAutoCommit(JdbcTransaction.java:100) Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@6166e06f] [DEBUG] 2019-08-17 09:09:12,369 method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:143) ==> Preparing: select *from user where id=? [DEBUG] 2019-08-17 09:09:12,389 method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:143) ==> Parameters: 1(Integer) [DEBUG] 2019-08-17 09:09:12,437 method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:143) <== Total: 1 domain.User@4d49af10 [DEBUG] 2019-08-17 09:09:12,451 method:org.apache.ibatis.transaction.jdbc.JdbcTransaction.resetAutoCommit(JdbcTransaction.java:122) Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@6166e06f] [DEBUG] 2019-08-17 09:09:12,451 method:org.apache.ibatis.transaction.jdbc.JdbcTransaction.close(JdbcTransaction.java:90) Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@6166e06f] [DEBUG] 2019-08-17 09:09:12,452 method:org.apache.ibatis.datasource.pooled.PooledDataSource.pushConnection(PooledDataSource.java:381) Returned connection 1634132079 to pool. [DEBUG] 2019-08-17 09:09:12,456 method:org.apache.ibatis.cache.decorators.LoggingCache.getObject(LoggingCache.java:60) Cache Hit Ratio [dao.IUserDao]: 0.5 domain.User@c540f5a false
五、总结
- 由 log 日志可知总共查询了一次,第二次是从缓存中查询的。
- 最后结果为 false,这个是因为二级缓存存储的是数据而不是对象
- {"id":1,"username":"老王","address":"北京"}
- 它会在第二次查询的时候创建一个新的对象,再把数据填充进去