Mybatis中的一级缓存和二级缓存

发布于:2022-12-14 ⋅ 阅读:(388) ⋅ 点赞:(0)

目录

一、什么是缓存?

二、什么是一级缓存?

1.JavaBean类:

2.Dao层:

3.mapper层:

4.view层:

 三、什么是二级缓存?

1.Mybatis中二级缓存的开启步骤:

1.1 在xml中开启

1.2 在注解中开启 

四、一级缓存和二级缓存的区别


一、什么是缓存?

缓存(cache),数据交换的缓冲区,当应用程序需要读取数据时,先从数据库中将数据取出,放置在 缓冲区中,应用程序从缓冲区读取数据。

Cache的特点:数据库取出的数据保存在内存中,具备快速读取和使用。
Cache的限制:读取时无需再从数据库获取,数据可能不是最新的。

二、什么是一级缓存?

一级缓存也叫SqlSession级缓存,无需手动开启可直接使用,为每个SqlSession单独分配的缓存空间,多个SqlSession之间的缓存不共享。

一级缓存实例如下:

1.JavaBean类:

package com.ape.bean;

import java.util.Date;

public class Student {
	private String sid;
	private String sname;
	private Date birthday;
	private String ssex;
	private int classid;
	public String getSid() {
		return sid;
	}
	public void setSid(String 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;
	}
	public Student() {
		super();
		// TODO Auto-generated constructor stub
	}
	public Student(String 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;
	}
	@Override
	public String toString() {
		return "Student [sid=" + sid + ", sname=" + sname + ", birthday=" + birthday + ", ssex=" + ssex + ", classid="
				+ classid + "]";
	}
	
}

2.Dao层:

package com.ape.dao;

import java.io.IOException;
import java.io.InputStream;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

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 block
			e.printStackTrace();
		}
		
	}
	
	public static SqlSession getSqlSession() {
		return build.openSession();
	}
	
	public static void closeResource(SqlSession sqlSession) {
		sqlSession.close();
	}
	
	
	
	
	

}

3.mapper层:

package com.ape.mapper;

import java.util.List;

import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Select;

import com.ape.bean.Student;

public interface IStudentMapper {
	//通过sid查询学生表中的数据
	@Select("select * from student where sid = #{sid}")
	List<Student> findStudentBySid(int sid);
	
	
	//通过sid删除学生表中的数据
	@Delete("delete from student where sid = #{sid}")
	int deleteStudentBySid(int sid);
}

4.view层:

package com.ape.test;

import java.util.List;

import org.apache.ibatis.session.SqlSession;

import com.ape.bean.Student;
import com.ape.dao.DaoUtil;
import com.ape.mapper.IStudentMapper;

public class Test1 {
	public static void main(String[] args) {
		SqlSession sql = DaoUtil.getSqlSession();
		IStudentMapper mapper = sql.getMapper(IStudentMapper.class);
		
		//第一次通过sid查询对应的数据
		List<Student> findStudentBySid1 = mapper.findStudentBySid(1);
		System.out.println(findStudentBySid1);
		
		
		System.out.println("----------------------------------------------------------");
		
		
		//第二次通过sid查询对应的数据
		List<Student> findStudentBySid2 = mapper.findStudentBySid(1);
		System.out.println(findStudentBySid2);
		
		
		//释放资源
		sql.close();
		
		
	}
}

运行结果:

什么情况下一级缓存会失效?
            1.用的不是同个SqlSession

package com.ape.test;

import java.util.List;

import org.apache.ibatis.session.SqlSession;

import com.ape.bean.Student;
import com.ape.dao.DaoUtil;
import com.ape.mapper.IStudentMapper;

public class Test1 {
	public static void main(String[] args) {
		//第一个SqlSession
		SqlSession sql1 = DaoUtil.getSqlSession();
		IStudentMapper mapper1 = sql1.getMapper(IStudentMapper.class);
		
		List<Student> findStudentBySid1 = mapper1.findStudentBySid(1);
		System.out.println(findStudentBySid1);
		
		
		System.out.println("-----------------------------------------------------------------------------------------------------");
		
		
		//第二个SqlSession
		SqlSession sql2 = DaoUtil.getSqlSession();
		IStudentMapper mapper2 = sql2.getMapper(IStudentMapper.class);
		
		List<Student> findStudentBySid2 = mapper2.findStudentBySid(1);
		System.out.println(findStudentBySid2);
		
		//释放资源
		sql1.close();
		sql2.close();
		
		
	}
}


            2.同一个SqlSession单查询条件不同

package com.ape.test;

import java.util.List;

import org.apache.ibatis.session.SqlSession;

import com.ape.bean.Student;
import com.ape.dao.DaoUtil;
import com.ape.mapper.IStudentMapper;

public class Test1 {
	public static void main(String[] args) {
		SqlSession sql = DaoUtil.getSqlSession();
		IStudentMapper mapper = sql.getMapper(IStudentMapper.class);

		//第一种单查询条件sid=1
		List<Student> findStudentBySid1 = mapper.findStudentBySid(1);
		System.out.println(findStudentBySid1);


		System.out.println("----------------------------------------------------------");


		//第二种单查询条件sid=2
		List<Student> findStudentBySid2 = mapper.findStudentBySid(2);
		System.out.println(findStudentBySid2);


		//释放资源
		sql.close();


	}
}


            3.同一个SqlSession做了增删改

package com.ape.test;

import java.util.List;

import org.apache.ibatis.session.SqlSession;

import com.ape.bean.Student;
import com.ape.dao.DaoUtil;
import com.ape.mapper.IStudentMapper;

public class Test1 {
	public static void main(String[] args) {
		SqlSession sql = DaoUtil.getSqlSession();
		IStudentMapper mapper = sql.getMapper(IStudentMapper.class);
		
		//第一次通过sid查询对应的数据
		List<Student> findStudentBySid1 = mapper.findStudentBySid(1);
		System.out.println(findStudentBySid1);
		
		//通过sid做一次删除操作
		int a = mapper.deleteStudentBySid(2);
		if (a > 0) {
			sql.commit();
			System.out.println("删除成功!");
		}else {
			sql.rollback();
			System.out.println("删除失败!");
		}
		
		System.out.println("----------------------------------------------------------");
		
		
		//第二次通过sid查询对应的数据
		List<Student> findStudentBySid2 = mapper.findStudentBySid(1);
		System.out.println(findStudentBySid2);
		
		
		//释放资源
		sql.close();
		
		
	}
}


            4.主动清空了缓存() 

package com.ape.test;

import java.util.List;

import org.apache.ibatis.session.SqlSession;

import com.ape.bean.Student;
import com.ape.dao.DaoUtil;
import com.ape.mapper.IStudentMapper;

public class Test1 {
	public static void main(String[] args) {
		SqlSession sql = DaoUtil.getSqlSession();
		IStudentMapper mapper = sql.getMapper(IStudentMapper.class);
		
		//第一次通过sid查询对应的数据
		List<Student> findStudentBySid1 = mapper.findStudentBySid(1);
		System.out.println(findStudentBySid1);
		
		//主动清空缓存
		sql.clearCache();
		
		System.out.println("----------------------------------------------------------");
		
		
		//第二次通过sid查询对应的数据
		List<Student> findStudentBySid2 = mapper.findStudentBySid(1);
		System.out.println(findStudentBySid2);
		
		
		//释放资源
		sql.close();
		
		
	}
}

 

 三、什么是二级缓存?

是mybatis的另一种缓存机制,区别于一级缓存,它是namespace级别,即一个mapper一个缓存,相互独立,互不影响,同一namespace下的多个sqlSession可以共享缓存,默认不开启,需要配置开启。

1.Mybatis中二级缓存的开启步骤:

1.1 在xml中开启

(1)在mybatis的sqlMapConfig.xml 中配置:

                                        

(2)在mybatis的sqlmap中配置(mapper.xml中配置):

(3)在使用的操作中配置(例如在select标签中配置) 

1.2 在注解中开启 

(1)在mybatis的sqlMapConfig.xml 中配置

(2)在接口的定义上面直接使用@CacheNamespace 并将blocking设置为true

二级缓存总结:

1.Mybatis 的二级缓存相对于一级缓存来说,实现了缓存数据的共享,可控性也更强。
2.极大可能会出现错误数据,有设计上的缺陷,安全使用的条件比较苛刻。

3.分布式环境下,必然会出现读取到错误数据,所以不推荐使用,了解即可。

四、一级缓存和二级缓存的区别

            1.一级缓存是SqlSession级别的而二级缓存是SqlSessionFactory级别的
            2.一级缓存写到了内存中而二级缓存直接序列化把写到了磁盘中
            3.一级缓存自动开启,二级缓存需要手动开启