1.一级缓存
Mybatis默认开启一级缓存,不需要我们额外配置。
一级缓存的对象为SqlSession对象,每个SqlSession对象都有缓存区,同一个SqlSession对象获取到的mapper映射器多次执行相同的查询只会对数据库查询一次。
一级缓存清空的时机:对数据库执行,增/删/改/事务提交(commit())/关闭close()时,一级缓存清空
2.二级缓存
Mybatis二级缓存的开启需要我们手动配置,二级缓存的对象为SqlSessionFactory,它存在于处理器的高速缓存(cache)中,注意:二级缓存的时数据,而不是对象,sqlSession取到数据后,会调用构造方法创建新的对象,然后把数据封装到对象中,所以我们得到的对象,地址不同。
-
mybatis核心配置文件
-
<settings> <setting name="cacheEnabled" value="true"/> </settings>
-
-
映射文件中声明
-
<cache/>
-
-
映射文件中方法声明
-
<select id="selectAll" resultType="user" useCache="true"> select * from myb_test </select>
-
3.案例
查询数据中所有的用户,从而观察一级缓存和二级缓存
log4j日志文件:log4j日志是为了方便我们对数据库方法进行观察
-
maven
-
<dependencies> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.7</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.22</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.27</version> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> </dependencies>
-
-
User.class
-
@Data @ToString public class User implements Serializable { private int id; private String name; private int age; private Date birthday; }
-
-
UserDao.class
-
public interface UserDao { /** * 查询所有用户 * @return */ List<User> selectAll(); }
-
-
UserMapper.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="com.z.dao.UserDao"> <!-- 二级缓存需要声明的配置2--> <!-- <cache/>--> <!-- 二级缓存需要在方法上开启的配置3--> <!-- <select id="selectAll" resultType="user" useCache="true">--> <select id="selectAll" resultType="user" > select * from myb_test </select> </mapper>
-
-
mybatis-config.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> <!-- 二级缓存需要开启的核心设置1--> <!-- <settings>--> <!-- <setting name="cacheEnabled" value="true"/>--> <!-- </settings>--> <typeAliases> <package name="com.z.dto"/> </typeAliases> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"></transactionManager> <dataSource type="POOLED"> <property name="driver" value="com.mysql.cj.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3307/train"/> <property name="username" value="root"/> <property name="password" value="520.hate"/> </dataSource> </environment> </environments> <mappers> <mapper resource="mapper/UserMapper.xml"/> </mappers> </configuration>
-
-
测试类
-
public class UserDaoTest { private SqlSessionFactory factory = null; private InputStream in = null; @Before public void init() throws IOException { in = Resources.getResourceAsStream("mybatis-config.xml"); factory = new SqlSessionFactoryBuilder().build(in); } /** * 二级缓存测试 */ @Test public void secondCache(){ SqlSession sqlSession1 = factory.openSession(); SqlSession sqlSession2 = factory.openSession(); SqlSession sqlSession3 = factory.openSession(); sqlSession1.getMapper(UserDao.class).selectAll(); sqlSession1.close(); //注意这里要close()清空一级缓存 sqlSession2.getMapper(UserDao.class).selectAll(); sqlSession2.close();//注意这里要close()清空一级缓存 sqlSession3.getMapper(UserDao.class).selectAll(); sqlSession3.close();//注意这里要close()清空一级缓存 } /** * 一级缓存测试 */ @Test public void firstCache(){ SqlSession sqlSession = factory.openSession(); UserDao userDao = sqlSession.getMapper(UserDao.class); List<User> users1 = userDao.selectAll(); List<User> users2 = userDao.selectAll(); System.out.println(users1 == users2); } @After public void destroy() throws IOException { in.close(); } }
-
-
log4j.xml
-
# Set root category priority to INFO and its only appender to CONSOLE. #log4j.rootCategory=INFO, CONSOLE debug info warn error fatal log4j.rootCategory=debug, CONSOLE, LOGFILE # Set the enterprise logger category to FATAL and its only appender to CONSOLE. log4j.logger.org.apache.axis.enterprise=FATAL, CONSOLE # CONSOLE is set to be a ConsoleAppender using a PatternLayout. log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout log4j.appender.CONSOLE.layout.ConversionPattern=%d{ISO8601} %-6r [%15.15t] %-5p %30.30c %x - %m\n # LOGFILE is set to be a File appender using a PatternLayout. log4j.appender.LOGFILE=org.apache.log4j.FileAppender log4j.appender.LOGFILE.File=D:\log log4j.appender.LOGFILE.Append=true log4j.appender.LOGFILE.layout=org.apache.log4j.PatternLayout log4j.appender.LOGFILE.layout.ConversionPattern=%d{ISO8601} %-6r [%15.15t] %-5p %30.30c %x - %m\n
-
一级缓存测试:
从结果可以看出,两次查询只对数据库访问一次,且user2 == user1 结果为true
,说明第二次查询是从sqlSession缓存中取数据的。
二级缓存测试:
虽然我们时使用sqlSession1,sqlSession2,sqlSession3对象
都执行一次查询,但是从日志上可以看到,对数据库只执行了一次查询,说明第二和第三次查询操作都是从二级缓存之中获取数据的。