缓存机制可以减轻数据库的压力,原理是在第一查询时,将查询结果缓存起来,之后再查询同样的sql,
不是真的去查询数据库,而是直接返回缓存中的结果。
缓存可以降低数据库的压力,但同时可能无法得到最新的结果数据。
1.数据库缓存的实现:
通过第三方工具实现缓存:
Redis内存数据库 - 可以实现缓存
通过MyBatis提供的缓存机制来实现缓存:
一级缓存:
缓存只在一个事务中有效,即同一个事务中先后执行多次同一个查询,只在第一次真正去查库,并将结果缓存,之后的查询都直接获取缓存中的中数据。如果是不同的事务,则缓存无效。
二级缓存:
缓存在全局有效,一个事务查询一个sql得到结果,会被缓存起来,之后只要缓存未被清楚,则其他事务如果查询同一个sql,得到的将会是之前缓存的结果。二级缓存作用范围大,作用时间长,可能造成的危害也更大,所以在开发中一般很少启用Mybatis的二级缓存。
2.MyBatis的一级缓存
MyBatis的一级缓存默认就是开启的
// 根据配置文件创建sqlSessionFactory private SqlSessionFactory factory = null; @Before public void before() throws Exception{ //1.读取MyBatis核心配置文件 InputStream in = Resources.getResourceAsStream("sqlMapConfig.xml"); //2.根据配置文件创建sqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in); } /** * 一级缓存 */ @Test public void test16(){ //1.创建sqlSession SqlSession session = factory.openSession(); //2.执行操作 List<User> list1 = session.selectList("cn.tedu.mybatis.beans.UserMapper.queryAll"); List<User> list2 = session.selectList("cn.tedu.mybatis.beans.UserMapper.queryAll"); //3.打印结果 System.out.println(list1); System.out.println(list2); }
测试结果:
2018-10-27 14:41:53,932 [main] DEBUG [cn.tedu.mybatis.beans.UserMapper.queryAll] - ooo Using Connection [com.mysql.jdbc.JDBC4Connection@18987a33] 2018-10-27 14:41:53,932 [main] DEBUG [cn.tedu.mybatis.beans.UserMapper.queryAll] - ==> Preparing: select * from user 2018-10-27 14:41:53,957 [main] DEBUG [cn.tedu.mybatis.beans.UserMapper.queryAll] - ==> Parameters: [User [id=1, name=aaa, age=19], User [id=2, name=bbb, age=29], User [id=4, name=ddd, age=22], User [id=5, name=eee, age=33], User [id=7, name=cjj, age=24]] [User [id=1, name=aaa, age=19], User [id=2, name=bbb, age=29], User [id=4, name=ddd, age=22], User [id=5, name=eee, age=33], User [id=7, name=cjj, age=24]]
只在第一次查询时走了数据库,后续的查询走缓存。
配置禁止一级缓存
<select id="queryAll" flushCache="true" resultType="Alias_User"> <include refid="saUser"/> </select>
2018-10-27 14:48:08,832 [main] DEBUG [cn.tedu.mybatis.beans.UserMapper.queryAll] - ooo Using Connection [com.mysql.jdbc.JDBC4Connection@427eb6e2]
2018-10-27 14:48:08,833 [main] DEBUG [cn.tedu.mybatis.beans.UserMapper.queryAll] - ==> Preparing: select * from user
2018-10-27 14:48:08,857 [main] DEBUG [cn.tedu.mybatis.beans.UserMapper.queryAll] - ==> Parameters:
2018-10-27 14:48:08,874 [main] DEBUG [cn.tedu.mybatis.beans.UserMapper.queryAll] - ooo Using Connection [com.mysql.jdbc.JDBC4Connection@427eb6e2]
2018-10-27 14:48:08,874 [main] DEBUG [cn.tedu.mybatis.beans.UserMapper.queryAll] - ==> Preparing: select * from user
2018-10-27 14:48:08,874 [main] DEBUG [cn.tedu.mybatis.beans.UserMapper.queryAll] - ==> Parameters:
[User [id=1, name=aaa, age=19], User [id=2, name=bbb, age=29], User [id=4, name=ddd, age=22], User [id=5, name=eee, age=33], User [id=7, name=cjj, age=24]]
[User [id=1, name=aaa, age=19], User [id=2, name=bbb, age=29], User [id=4, name=ddd, age=22], User [id=5, name=eee, age=33], User [id=7, name=cjj, age=24]]
3.MyBatis的二级缓存
MyBatis的二级缓存默认是关闭的
// 根据配置文件创建sqlSessionFactory private SqlSessionFactory factory = null; @Before public void before() throws Exception{ //1.读取MyBatis核心配置文件 InputStream in = Resources.getResourceAsStream("sqlMapConfig.xml"); //2.根据配置文件创建sqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in); } /** * 缓存机制:二级缓存 */ @Test public void test17(){ //1.第一次事务 SqlSession session1 = factory.openSession(); User user1 = session1.selectOne( "cn.tedu.mybatis.beans.UserMapper.queryOne",1); session1.commit(); //2.第二次事务 SqlSession session2 = factory.openSession(); User user2 = session2.selectOne( "cn.tedu.mybatis.beans.UserMapper.queryOne",1); session2.commit(); //3.打印结果 System.out.println(user1); System.out.println(user2); }
测试结果:
2018-10-27 14:49:58,913 [main] DEBUG [cn.tedu.mybatis.beans.UserMapper.queryOne] - ooo Using Connection [com.mysql.jdbc.JDBC4Connection@58648016] 2018-10-27 14:49:58,913 [main] DEBUG [cn.tedu.mybatis.beans.UserMapper.queryOne] - ==> Preparing: select * from user where id = ? 2018-10-27 14:49:58,935 [main] DEBUG [cn.tedu.mybatis.beans.UserMapper.queryOne] - ==> Parameters: 1(Integer) 2018-10-27 14:49:58,959 [main] DEBUG [cn.tedu.mybatis.beans.UserMapper.queryOne] - ooo Using Connection [com.mysql.jdbc.JDBC4Connection@35f03691] 2018-10-27 14:49:58,959 [main] DEBUG [cn.tedu.mybatis.beans.UserMapper.queryOne] - ==> Preparing: select * from user where id = ? 2018-10-27 14:49:58,959 [main] DEBUG [cn.tedu.mybatis.beans.UserMapper.queryOne] - ==> Parameters: 1(Integer) User [id=1, name=aaa, age=19] User [id=1, name=aaa, age=19]
配置选项开启二级缓存
在sqlMapConfig.xml配置
<!-- 开启二级缓存 --> <settings> <setting name="cacheEnabled" value="true"/> </settings>
在映射文件中配置
想要被二级缓存缓存的bean必须实现序列化接口
测试类:
运行结果:
2018-10-27 14:57:36,745 [main] DEBUG [cn.tedu.mybatis.beans.UserMapper.queryOne] - ooo Using Connection [com.mysql.jdbc.JDBC4Connection@1dd49247]
2018-10-27 14:57:36,746 [main] DEBUG [cn.tedu.mybatis.beans.UserMapper.queryOne] - ==> Preparing: select * from user where id = ?
2018-10-27 14:57:36,772 [main] DEBUG [cn.tedu.mybatis.beans.UserMapper.queryOne] - ==> Parameters: 1(Integer)
User [id=1, name=aaa, age=19]
User [id=1, name=aaa, age=19]