这一章我想分成两节,分别讲解一级缓存和二级缓存。
- 什么是查询缓存?
mybatis提供查询缓存,用于减轻数据压力,提高数据库性能。
mybatis提供一级缓存和二级缓存。 - 如图:
一级缓存:是SqlSession级别的缓存。在操作数据库时需要构造 sqlSession对象,在对象中有一个数据结构(HashMap)用于存储缓存数据。不同的sqlSession之间的缓存数据区域(HashMap)是互相不影响的。
二级缓存:是mapper级别的缓存,多个SqlSession去操作同一个Mapper的sql语句,多个SqlSession可以共用二级缓存,二级缓存是跨SqlSession的。 - 为什么要使用缓存?
如果缓存中有数据就不用从数据库中获取,大大提高系统性能。
一级缓存原理:
说明:
第一次发起查询用户id为1的用户信息,先去找缓存中是否有id为1的用户信息,如果没有,从数据库查询用户信息。
得到用户信息,将用户信息存储到一级缓存中。
如果sqlSession去执行commit操作(执行插入、更新、删除),清空SqlSession中的一级缓存,这样做的目的为了让缓存中存储的是最新的信息,避免脏读。
第二次发起查询用户id为1的用户信息,先去找缓存中是否有id为1的用户信息,缓存中有,直接从缓存中获取用户信息。
测试:
mybatis默认支持一级缓存,所以不需要配置
看下测试代码:
package cn.mybatis.mapper.test;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import cn.mybatis.mapper.UserMapper;
import cn.mybatis.pojo.User;
public class UserMapperTest {
private SqlSessionFactory sqlSessionFactory;
private SqlSession sqlSession;
@Before
public void setUp() throws Exception {
sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources
.getResourceAsStream("MyBatisConfig.xml"));
sqlSession = sqlSessionFactory.openSession();
}
@After
public void tearDown() throws Exception {
sqlSession.close();
}
@Test
// 一级缓存测试
public void testFindUserById() throws Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
// 第一次发出请求
Long beginTimes = System.currentTimeMillis();
User user1 = userMapper.findUserById(1);
Long endTimes = System.currentTimeMillis();
System.out.println(user1);
System.out.println("第一次请求,共花费:" + (endTimes - beginTimes));
// 第二次发出请求
Long beginTimes2 = System.currentTimeMillis();
User user2 = userMapper.findUserById(1);
Long endTimes2 = System.currentTimeMillis();
System.out.println(user2);
System.out.println("第二次请求,共花费:" + (endTimes2 - beginTimes2));
}
}
输出结果分别是:
User [id=1, username=紫衫龙王, sex=2, birthday=Mon Sep 14 00:00:00 CST 2015, address=盐城]
第一次请求,共花费:320
User [id=1, username=紫衫龙王, sex=2, birthday=Mon Sep 14 00:00:00 CST 2015, address=盐城]
第二次请求,共花费:0
结果很明显了,就不用多说了。
第二种情况:更新下数据commit一下
@Test
public void testUpdateUser() throws Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
// 1、第一次请求
Long beginTimes = System.currentTimeMillis();
User user1 = userMapper.findUserById(1);
Long endTimes = System.currentTimeMillis();
System.out.println(user1);
System.out.println("第一次请求,共花费:" + (endTimes - beginTimes));
// 更新数据
user1.setUsername("紫衫龙王");//金毛狮王、轻翼蝠王、紫衫龙王
Long beginTimes3 = System.currentTimeMillis();
userMapper.updateUser(user1);
Long endTimes3 = System.currentTimeMillis();
System.out.println("更新,共花费:" + (endTimes3 - beginTimes3));
System.out.println(user1);
// 清空缓存
sqlSession.commit();
// 2、第二次请求
Long beginTimes2 = System.currentTimeMillis();
User user2 = userMapper.findUserById(1);
Long endTimes2 = System.currentTimeMillis();
System.out.println(user2);
System.out.println("第二次共花费:" + (endTimes2 - beginTimes2));
}
运行结果:
User [id=1, username=紫衫龙王, sex=2, birthday=Mon Sep 14 00:00:00 CST 2015, address=盐城]
第一次请求,共花费:300
2016-04-06 15:37:59,880 [main] DEBUG [cn.mybatis.mapper.UserMapper.updateUser] - ==> Preparing: update user set username=?,birthday=?,sex=?,address=? where id=?
2016-04-06 15:37:59,884 [main] DEBUG [cn.mybatis.mapper.UserMapper.updateUser] - ==> Parameters: 紫衫龙王(String), 2015-09-14 00:00:00.0(Timestamp), 2(String), 盐城(String), 1(Integer)
2016-04-06 15:37:59,885 [main] DEBUG [cn.mybatis.mapper.UserMapper.updateUser] - <== Updates: 1
更新,共花费:6
User [id=1, username=紫衫龙王, sex=2, birthday=Mon Sep 14 00:00:00 CST 2015, address=盐城]
2016-04-06 15:37:59,964 [main] DEBUG [cn.mybatis.mapper.UserMapper.findUserById] - ==> Preparing: select * from user where id = ?
2016-04-06 15:37:59,964 [main] DEBUG [cn.mybatis.mapper.UserMapper.findUserById] - ==> Parameters: 1(Integer)
2016-04-06 15:37:59,965 [main] DEBUG [cn.mybatis.mapper.UserMapper.findUserById] - <== Total: 1
User [id=1, username=紫衫龙王, sex=2, birthday=Mon Sep 14 00:00:00 CST 2015, address=盐城]
第二次共花费:1
虽然只有1mm,但也是去查询的毕竟大部分数据没有变动只是改了一个名字。
一级缓存应用:
正式开发,是将mybatis和spring进行整合开发,事务控制在service中。
一个service方法中包括很多mapper方法调用。
service{
//开始执行时,开启事务,创建SqlSession对象
//第一次调用mapper的方法findUserById(1)
//第二次调用mapper的方法findUserById(1),从一级缓存中取数据
//方法结束,sqlSession关闭
}
如果是执行两次service调用查询相同的用户信息,不走一级缓存,因为session方法结束,sqlSession就关闭,一级缓存就清空。
热门评论
好,Springboot在哪里,没找到啊
好
想知道mybatis前几张在何处