一:MyBatis缓存简介
MyBatis支持声明式数据缓存(declarative data caching)。当一条SQL语句被标记为“可缓存”后,首次执行它时从数据库获取的所有数据会被存储在一段高速缓存中,今后执行这条语句时就会从高速缓存中读取结果,而不是再次命中数据库。MyBatis提供了默认下基于Java HashMap的缓存实现,以及用于与OSCache、Ehcache、Hazelcast和Memcached连接的默认连接器。MyBatis还提供API供其他缓存实现使用。
MyBatis执行SQL语句之后,这条语句就是被缓存,以后再执行这条语句的时候,会直接从缓存中拿结果,而不是再次执行SQL,这就是所说的一级缓存。一级缓存的作用域scope是SqlSession。
一级缓存
测试
同个session进行两次相同查询:
1 @Test 2 public void test() { 3 SqlSession sqlSession = sqlSessionFactory.openSession(); 4 try { 5 User user = (User)sqlSession.selectOne("org.format.mybatis.cache.UserMapper.getById", 1); 6 log.debug(user); 7 User user2 = (User)sqlSession.selectOne("org.format.mybatis.cache.UserMapper.getById", 1); 8 log.debug(user2); 9 } finally { 10 sqlSession.close(); 11 } 12 }
MyBatis只进行1次数据库查询:
1 ==> Preparing: select * from USERS WHERE ID = ? 2 ==> Parameters: 1(Integer) 3 <== Total: 1 4 User{id=1, name='format', age=23, birthday=Sun Oct 12 23:20:13 CST 2017} 5 User{id=1, name='format', age=23, birthday=Sun Oct 12 23:20:13 CST 2017}
同个session进行两次不同的查询:
1 @Test 2 public void test() { 3 SqlSession sqlSession = sqlSessionFactory.openSession(); 4 try { 5 User user = (User)sqlSession.selectOne("org.format.mybatis.cache.UserMapper.getById", 1); 6 log.debug(user); 7 User user2 = (User)sqlSession.selectOne("org.format.mybatis.cache.UserMapper.getById", 2); 8 log.debug(user2); 9 } finally { 10 sqlSession.close(); 11 } 12 }
MyBatis进行两次数据库查询:
1 ==> Preparing: select * from USERS WHERE ID = ? 2 ==> Parameters: 1(Integer) 3 <== Total: 1 4 User{id=1, name='format', age=23, birthday=Sun Oct 12 23:20:13 CST 2017} 5 ==> Preparing: select * from USERS WHERE ID = ? 6 ==> Parameters: 2(Integer) 7 <== Total: 1 8 User{id=2, name='FFF', age=50, birthday=Sat Dec 06 17:12:01 CST 2017}
不同session,进行相同查询:
1 @Test 2 public void test() { 3 SqlSession sqlSession = sqlSessionFactory.openSession(); 4 SqlSession sqlSession2 = sqlSessionFactory.openSession(); 5 try { 6 User user = (User)sqlSession.selectOne("org.format.mybatis.cache.UserMapper.getById", 1); 7 log.debug(user); 8 User user2 = (User)sqlSession2.selectOne("org.format.mybatis.cache.UserMapper.getById", 1); 9 log.debug(user2); 10 } finally { 11 sqlSession.close(); 12 sqlSession2.close(); 13 } 14 }
MyBatis进行了两次数据库查询:
1 ==> Preparing: select * from USERS WHERE ID = ? 2 ==> Parameters: 1(Integer) 3 <== Total: 1 4 User{id=1, name='format', age=23, birthday=Sun Oct 12 23:20:13 CST 2017} 5 ==> Preparing: select * from USERS WHERE ID = ? 6 ==> Parameters: 1(Integer) 7 <== Total: 1 8 User{id=1, name='format', age=23, birthday=Sun Oct 12 23:20:13 CST 2017}
同个session,查询之后更新数据,再次查询相同的语句:
1 @Test 2 public void test() { 3 SqlSession sqlSession = sqlSessionFactory.openSession(); 4 try { 5 User user = (User)sqlSession.selectOne("org.format.mybatis.cache.UserMapper.getById", 1); 6 log.debug(user); 7 user.setAge(100); 8 sqlSession.update("org.format.mybatis.cache.UserMapper.update", user); 9 User user2 = (User)sqlSession.selectOne("org.format.mybatis.cache.UserMapper.getById", 1); 10 log.debug(user2); 11 sqlSession.commit(); 12 } finally { 13 sqlSession.close(); 14 } 15 }
更新操作之后缓存会被清除:
1 ==> Preparing: select * from USERS WHERE ID = ? 2 ==> Parameters: 1(Integer) 3 <== Total: 1 4 User{id=1, name='format', age=23, birthday=Sun Oct 12 23:20:13 CST 2017} 5 ==> Preparing: update USERS SET NAME = ? , AGE = ? , BIRTHDAY = ? where ID = ? 6 ==> Parameters: format(String), 23(Integer), 2017-10-12 23:20:13.0(Timestamp), 1(Integer) 7 <== Updates: 1 8 ==> Preparing: select * from USERS WHERE ID = ? 9 ==> Parameters: 1(Integer) 10 <== Total: 1 11 User{id=1, name='format', age=23, birthday=Sun Oct 12 23:20:13 CST 2017}
很明显,结果验证了一级缓存的概念,在同个SqlSession中,查询语句相同的sql会被缓存,但是一旦执行新增或更新或删除操作,缓存就会被清除