缓存即为存在内存中的临时数据.将用户经常查询的数据存放在缓存(内存)中,用户去查询数据就不用去每次去数据库中查询,而是去缓存中查询,从而提高了查询的效率,解决了高并发系统的性能问题.
使用缓存的方式可以减少和数据库的交互次数,减少系统开销,提高系统效率
将经常查询的并且不经常改变的数据适合使用缓存;反之,不经常查询且经常改变的数据不适合使用缓存
Mybatis中将缓存分为一级缓存和二级缓存
一级缓存是Mybatis默认开启的缓存,我们不用自己去手动开启.它是SQLSession级别的缓存,也称为本地缓存,当调用SqlSession的修改,添加,删除,commit().close(),clearCache()等方法时就会清空一次一级缓存.
一次查询的结果我们将它暂时存放在缓存中,我们下次再去查询的时候就可以去缓存中查找,而不用去与数据库交互查询.
栗子:
此处我们以查询学生列表为例
1.接口中的方法:
List findStudentlist(Student student);
2.mapper.xml:
SELECT s.id,s.name,s.gender,g.name gname
FROM student s
LEFT JOIN grade g
ON s.gradeid = g.id
LEFT JOIN admin a
ON s.adminid = a.id
3.测试类:
package com.ffyc.mybatisdemo.test;
import com.ffyc.mybatisdemo.dao.StudentDao;
import com.ffyc.mybatisdemo.model.Student;
import com.ffyc.mybatisdemo.util.MybatisUtil;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
/*
多表查询 多对1
*/
public class TestStudent {
@Test
//一级缓存
public void cacheDemo() {
SqlSession sqlSession = MybatisUtil.getSqlSession();
StudentDao studentDao = sqlSession.getMapper(StudentDao.class);
Student student = new Student();
List students = studentDao.findStudentlist(student);
System.out.println(students);
System.out.println("-----------------------------");
List students2 = studentDao.findStudentlist(student);
System.out.println(students2);
sqlSession.close(); //关闭SQLSession,会清空一级缓存
}
}
由查询结果我们可以看到,我们执行了两次相同的查询方法,但是从日志中可以看到,只执行了一次查询语句.这就体现出了一级缓存的作用,我们不用频繁与数据库进行交互.
二级缓存是SQLSessionFactory级别的缓存,作用域为一个namespace,也就是在同一个mapper下都会生效,由多SqlSession所共享.需要我们手动开启和配置.
注:
二级缓存只有在一级缓存死掉的时候才会生效.
二级缓存的配置:
1.开启全局二级缓存:
2.将所有实体类实现实例化接口: java.io.Serializable
public class Admin implements Serializable{
}
3.配置映射文件:
mapper映射在配置文件中添加
栗子:
这里我们还是以之前的查询学生列表为例:
1.接口中的方法:
List findStudentlist(Student student);
2.mapper.xml:
SELECT s.id,s.name,s.gender,g.name gname
FROM student s
LEFT JOIN grade g
ON s.gradeid = g.id
LEFT JOIN admin a
ON s.adminid = a.id
3.测试类:
package com.ffyc.mybatisdemo.test;
import com.ffyc.mybatisdemo.dao.StudentDao;
import com.ffyc.mybatisdemo.model.Student;
import com.ffyc.mybatisdemo.util.MybatisUtil;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
public class TestStudent {
@Test
//二级缓存
public void cacheDemo2() {
SqlSession sqlSession = MybatisUtil.getSqlSession();
StudentDao studentDao = sqlSession.getMapper(StudentDao.class);
Student student = new Student();
List students = studentDao.findStudentlist(student);
System.out.println(students);
SqlSession sqlSession2 = MybatisUtil.getSqlSession();
StudentDao studentDao2 = sqlSession2.getMapper(StudentDao.class);
List students2 = studentDao2.findStudentlist(student);
System.out.println(students2);
sqlSession.close();
}
}
修改:
package com.ffyc.mybatisdemo.test;
import com.ffyc.mybatisdemo.dao.StudentDao;
import com.ffyc.mybatisdemo.model.Student;
import com.ffyc.mybatisdemo.util.MybatisUtil;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
public class TestStudent {
@Test
//二级缓存
public void cacheDemo2() {
SqlSession sqlSession1 = MybatisUtil.getSqlSession();
StudentDao studentDao = sqlSession1.getMapper(StudentDao.class);
SqlSession sqlSession2 = MybatisUtil.getSqlSession();
StudentDao studentDao2 = sqlSession2.getMapper(StudentDao.class);
Student student = new Student();
List students = studentDao.findStudentlist(student);
System.out.println(students);
sqlSession1.close(); //关闭SQLSession,会清空一级缓存,并将一级缓存中的数据放入二级缓存中
List students2 = studentDao2.findStudentlist(student);
System.out.println(students2);
sqlSession2.close();
}
}
Mybatis的一级缓存时SqlSession级别的缓存,一级缓存缓存的是对象,当SqlSession提交,关闭,以及其他的更新数据库的操作发生时,以及缓存就会被清空.
二级缓存是SQLSessionFactory级别的缓存,同一个SQLSessionFactory产生的SqlSession都共享一个二级缓存,二级缓存中存储的是数据,当命中二级缓存时,通过存储的数据构成对象返回.