Mybatis一级缓存和二级缓存
缓存到底是什么东西呢??
缓存是数据交换的缓冲区,简单点理解就是存在于内存中的临时数据。
那我们为什么要使用缓存?
例如我们每次查询用户信息,每次都要请求数据库,数据库会编译并执行你的SQL语句,这样效率就会很低。针对一些频繁访问并不经常改变的数据,而且数据量较大的情况,通常做法,就是把他加入缓存,每次取数前先去判断,如果缓存不为空,那么就从缓存取值,如果为空,再去请求数据库,并将数据加入缓存。
缓存的目的就是:减少和数据库的交互次数,提高执行效率。
大概了解了一下缓存的概念我们现在开始聊聊Mybatis中的缓存吧!下面会分别介绍一下Mybatis中的一级缓存和二级缓存。
这里先把目录结构给放出来
UserDao接口
public interface UserDao {
/**
* 根据id查询用户信息
*/
User findById(Integer id);
}
User类(实体类)
public class User implements Serializable {
private Integer id;
private String username;
private Date birthday;
private String sex;
private String address;
public User() {
}
为了代码篇幅,这里省略了getter和setter方法
}
Mybatis主配置文件SqlMapConfig.xml
/p>
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
UserDao.xml(dao映射文件)
/p>
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
select * from user where id = #{uid}
一级缓存:Mybatis中SqlSession对象的缓存
当我们执行查询之后,查询的结果会同时存入到SqlSession中的一块区域。当我们再次查询同样的数据时,Mybatis会先去SqlSession中查询是否有,有的话就直接使用不用再次请求数据库。
测试一级缓存
一级缓存是 SqlSession范围的缓存,当调用 SqlSession的修改,添加,删除,commit(),close()、clearCache()
通过两次查询同一个id,看第二次是否再次执行了查询语句就可以说明是否使用了一级缓存。也可通过两次是否是同一个对象说明。
public class FirstLevelCacheTest {
InputStream in;
SqlSessionFactoryBuilder builder;
SqlSessionFactory factory;
SqlSession session;
UserDao userDao;
/**
* 标注了Before注解会在执行Test方法之前执行
* @throws Exception
*/
@Before
public void init() throws Exception{
//1.读取配置文件
in = Resources.getResourceAsStream("SqlMapConfig.xml");
//2.创建SqlSessionFactory工厂
builder = new SqlSessionFactoryBuilder();
factory = builder.build(in);
//3.使用工厂生产SqlSession对象
session = factory.openSession();
//4.使用SqlSession创建dao接口代理对象
userDao = session.getMapper(UserDao.class);
}
/**
* 标注了After注解会在执行Test方法之后执行
* @throws Exception
*/
@After
public void destroy()throws Exception{
//提交事务
session.commit();
//6.释放资源
session.close();
in.close();
}
@Test
public void testCache(){
User user1 = userDao.findById(45);
System.out.println(user1);
//此句话为清理缓存
//session.clearCache();
User user2 = userDao.findById(45);
System.out.println(user2);
//通过比较两次是否是同一个对象
System.out.println(user1==user2);
}
}
结果:
当我们把session.clearCache();这句话的注释打开,这句话的意思是清理了SqlSession对象缓存,即清理了一级缓存。我们会发现,第二次查询又会请求了数据库。
二级缓存:Mybatis中SqlsessionFactory对象的缓存,同一个SqlsessionFactory创建的SqlSession对象共享缓存
要使用Mybatis的二级缓存还需要额外的配置
在Mybatis主配置文件中配置 ,即上面的SqlMapConfig.xml
在dao的映射文件中配置 和在select标签中配置useCache="true",即上面的UserDao.xml
/p>
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
select * from user where id = #{uid}
测试二级缓存
通过同一个SqlSessionFactory对象创建的两个sqlSession测试,
在用sqlSession1执行查询操作之后,我们调用sqlSession1.close(),把一级缓存关闭,第二次用sqlSession2再次进行查询,因为上面已经关闭了一级缓存,而且时不同的sqlSession对象,第二次查询的结果如果没用执行sql语句说明二级缓存生效了!
public class SecondLevelCacheTest {
InputStream in;
SqlSessionFactoryBuilder builder;
SqlSessionFactory factory;
/**
* 标注了Before注解会在执行Test方法之前执行
* @throws Exception
*/
@Before
public void init() throws Exception{
//1.读取配置文件
in = Resources.getResourceAsStream("SqlMapConfig.xml");
//2.创建SqlSessionFactory工厂
builder = new SqlSessionFactoryBuilder();
factory = builder.build(in);
//3.使用工厂生产SqlSession对象
}
/**
* 标注了After注解会在执行Test方法之后执行
* @throws Exception
*/
@After
public void destroy()throws Exception{
in.close();
}
@Test
public void testCache(){
SqlSession sqlSession1 = factory.openSession();
UserDao dao1 = sqlSession1.getMapper(UserDao.class);
User user1 = dao1.findById(45);
sqlSession1.close();
SqlSession sqlSession2 = factory.openSession();
UserDao dao2 = sqlSession2.getMapper(UserDao.class);
User user2 = dao2.findById(45);
sqlSession2.close();
}
}
注意:当我们在使用二级缓存时,所缓存的类一定要实现java.io.Serializable接口,这种就可以使用序列化方式来保存对象。