Mybatis一级缓存和二级缓存分别是什么,区别是什么?
一、概念
1.一级缓存:是基于数据库会话的,并且默认开启。一级缓存的作用域为SqlSession。在同一个SqlSession中,执行相同的sql语句,那么第一次就会去数据库中进行查询,并写到缓存中,如果我们后面还想去访问数据库查询,就直接去一级缓存中获取就可以了。
2.二级缓存:是基于全局的,不能默认开启,开启时需要手动配置。二级缓存的作用域为SqlSessionFactory,是一个映射器级别的缓存,针对不同namespace的映射器。一个会话中,查询一条数据,这个数据会被放到一级缓存中,但是一旦这个会话关闭,一级缓存汇总的数据就会被保存到二级缓存。新的会话查询信息就会参照二级缓存中存储的信息。
二、工作流程
1.一级缓存

我们能从图中看出:
a.对于某个Select Statement,根据Statement生成key;
b.判断在local cache中,该key是否用对应的数据存在
c.判断查询结果如果不为空则跳过数据库继续执行下面的语句
d.如果为空,就去数据库中查询数据,能取到一个结果
e.将key和查询到的结果作为key和value,放入local cache中
f.判断缓存级别是否为statement级别,如果是,清空本地缓存
2.二级缓存

二级缓存的大致流程:
a.开启两个会话
b.在会话一中查询结果加入一级缓存
c.在会话二中查询二级缓存是否有数据
d.如果有数据取二级缓存中的数据
e.如果没有就去查询一级缓存中是否有数据
f.如果没有那么连接数据库进行查询
g.如果有就取一级缓存中的数据
三、一级缓存失效情况
1.不同sqlSesiion对应不同的一级缓存
2.同一个sqlSession单查询条件不同
3.同一个sqlSession两次查询期间执行了任何一次增删改操作
4.同一个sqlSession两次查询期间手动清空了缓存
四、一级缓存与二级缓存的区别
1.一级缓存
a.sqlSession级别的
b.默认是开启的
2.二级缓存
a.sql SessionFactory(namespace)
b.默认是关闭的
c.放在二级的对象要实现对象序列化接口
d.二级缓存可以使用第三方的
五、一级缓存和二级缓存的相同点
1.一级缓存和二级缓存都是用perpetualcache来实现的
2.mybatis执行更新操作后,一级缓存和二级缓存都会被刷新
六、一级缓存失效实例
学生类:
public class Student {private int sid;private String sname;private Date birthday;private String ssex;private int classid;public Student(int sid, String sname, Date birthday, String ssex, int classid) {super();this.sid = sid;this.sname = sname;this.birthday = birthday;this.ssex = ssex;this.classid = classid;}public Student() {super();}public int getSid() {return sid;}public void setSid(int sid) {this.sid = sid;}public String getSname() {return sname;}public void setSname(String sname) {this.sname = sname;}public Date getBirthday() {return birthday;}public void setBirthday(Date birthday) {this.birthday = birthday;}public String getSsex() {return ssex;}public void setSsex(String ssex) {this.ssex = ssex;}public int getClassid() {return classid;}public void setClassid(int classid) {this.classid = classid;}
Dao层 :
public class DaoUtil {private static SqlSessionFactory build;static {try {InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");build=new SqlSessionFactoryBuilder().build(resourceAsStream);} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}public static SqlSession getSqlSession() {return build.openSession();}public static void closeResource(SqlSession SqlSession) {SqlSession.close();}}
接口层:
public interface StudentMapper {@Select("select * from student")public List findAllStudent();@Select("select * from student where sid=#{sid}")public Student findStudentBysid(int sid);@Insert("insert into student(sname) values('张三')")public int addStudent();}
测试:
public static void main(String[] args) {SqlSession sqlSession = DaoUtil.getSqlSession();StudentMapper stumapper = sqlSession.getMapper(StudentMapper.class);Student s = stumapper.findStudentBysid(5);System.out.println(s);for(int i = 0; i< 100;i++) {System.out.print(".");}// 增删改
// int ret = stumapper.addStudent();// 清空缓存sqlSession.clearCache();System.out.println();Student s2 = stumapper.findStudentBysid(5);System.out.println(s2);System.out.println(s == s2);DaoUtil.closeResource(sqlSession);}}
运行之后我们能看到只要手动清空缓存,那么一级缓存就会失效。
当我们把代码改成新增时再次运行:
public class Demo2 {public static void main(String[] args) {SqlSession sqlSession = DaoUtil.getSqlSession();StudentMapper stumapper = sqlSession.getMapper(StudentMapper.class);Student s = stumapper.findStudentBysid(4);System.out.println(s);for(int i = 0; i< 100;i++) {System.out.print(".");}// 增删改int ret = stumapper.addStudent();// 清空缓存
// sqlSession.clearCache();System.out.println();Student s2 = stumapper.findStudentBysid(4);System.out.println(s2);System.out.println(s == s2);DaoUtil.closeResource(sqlSession);}}

答案还是false,说明新增情况下,一级缓存也会失效,此外删除和修改也是同样的效果。
当然不同的sqlSession对象也会使一级缓存失效:
public class Demo3 {public static void main(String[] args) {SqlSession sqlSession1 = DaoUtil.getSqlSession();StudentMapper mapper1 = sqlSession1.getMapper(StudentMapper.class);Student s1 = mapper1.findStudentBysid(5);System.out.println(s1);DaoUtil.closeResource(sqlSession1);SqlSession sqlSession2 = DaoUtil.getSqlSession();StudentMapper mapper2 = sqlSession2.getMapper(StudentMapper.class);Student s2 = mapper2.findStudentBysid(5);System.out.println(s2);DaoUtil.closeResource(sqlSession2);System.out.println(s1 == s2);}}
运行情况如下图:

七、总结
mybatis的的一级缓存是SqlSession级别的缓存,一级缓存缓存的是对象,当SqlSession提
交、关闭以及其他的更新数据库的操作发生后,一级缓存就会清空。二级缓存SqlSessionFactory
级别的缓存,同一个SqlSessionFactory产生的SqlSession都共享一个二级缓存,二级缓存中存储
的是数据,当命中二级缓存时,通过存储的数据构造对象返回。查询数据的时候,查询的流程是二
级缓存>一级缓存>数据库。
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
