首先创建项目,这里就不使用Spring框架了,直接用mybatis原生:
文章目录- 准备工作
- 一级缓存:
- 二级缓存
首先创建maven项目,引入依赖:
org.mybatis
mybatis
3.5.7
mysql
mysql-connector-java
8.0.26
创建我们的实体类:
public class Blog {
private String name;
private Integer id;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
@Override
public String toString() {
return "Blog{" +
"name='" + name + ''' +
", id=" + id +
'}';
}
}
配置我们的mybtais 的配置文件 mybatis-config.xml:
我们要在数据库里面有配置好该实体类对应的表:
创建Mapper类 BlogMapper:
public interface BlogMapper {
public Blog selectBlog(Integer id);
}
创建其对应的mapper文件:
还有一个类:
public class MyBatisConfig {
public static SqlSessionFactory getSqlSessionFactory(){
String resource = "com/learning/mybatis-config.xml";
InputStream inputStream = null;
try {
inputStream = Resources.getResourceAsStream(resource);
} catch (IOException e) {
e.printStackTrace();
}
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
return sqlSessionFactory;
}
}
此时目录结构如下:
上面是准备工作,接下来测试一级缓存和二级缓存
一级缓存:public class Starter {
public static void main(String[] args) {
SqlSessionFactory sqlSessionFactory = MyBatisConfig.getSqlSessionFactory();
SqlSession sqlSession = sqlSessionFactory.openSession();
BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
Blog blog1 = mapper.selectBlog(1);
System.out.println("blog1的值是"+blog1);
blog1.setName("修改成我设置的值");
System.out.println("=============开始同一个 Sqlsession 的第二次查询============");
Blog blog2 = mapper.selectBlog(1);
System.out.println("blog2的值是"+blog2);
System.out.println("判断blog1和blog2对象是否相等"+blog1.equals(blog2));
sqlSession.close();
}
}
运行之后如下:
可以发现,第二次拿到的值就是第一次拿到的对象。
如果我们这两次查询使用的是不同的SqlSession,如下:
public static void main(String[] args) {
SqlSessionFactory sqlSessionFactory = MyBatisConfig.getSqlSessionFactory();
SqlSession sqlSession1 = sqlSessionFactory.openSession();
SqlSession sqlSession2 = sqlSessionFactory.openSession();
BlogMapper blogMapper1 = sqlSession1.getMapper(BlogMapper.class);
BlogMapper blogMapper2 = sqlSession2.getMapper(BlogMapper.class);
Blog blog1 = blogMapper1.selectBlog(1);
Blog blog2 = blogMapper2.selectBlog(2);
System.out.println("判断两个对象是否相等: "+blog1.equals(blog2));
sqlSession1.close();
sqlSession2.close();
}
使用上面的代码进行执行:
发现两个对象不相等,说明一级缓存只作用于同一个SqlSeesion
一级缓存是SqlSession级别的缓存。在操作数据库时需要构造 sqlSession对象,一级缓存的作用域是同一个SqlSession,在同一个sqlSession中两次执行相同的sql语句,第一次执行完毕会将数据库中查询的数据写到缓存(内存),第二次会从缓存中获取数据将不再从数据库查询,从而提高查询效率。当一个sqlSession结束后该sqlSession中的一级缓存也就不存在了。一级缓存是默认开启的
二级缓存二级缓存不是默认开启的。我们要使用二级缓存需要去mapper映射文件配置:
如上,使用
public class Blog implements Serializable {
private static final long serialVersionUID = -7946444982033976955L;
。。。
}
执行如下代码:
public static void main(String[] args) {
SqlSessionFactory sqlSessionFactory = MyBatisConfig.getSqlSessionFactory();
SqlSession session = sqlSessionFactory.openSession();
BlogMapper mapper = session.getMapper(BlogMapper.class);
Blog blog1 = mapper.selectBlog(1);
System.out.println(blog1);
System.out.println("第二次执行");
Blog blog2 = mapper.selectBlog(1);
System.out.println(blog2);
session.commit();
System.out.println("二级缓存观测点");
SqlSession session2 = sqlSessionFactory.openSession();
BlogMapper mapper2 = session2.getMapper(BlogMapper.class);
Blog blog3 = mapper2.selectBlog(1);
System.out.println(blog3);
System.out.println("第二次执行");
Blog blog4 = mapper2.selectBlog(1);
System.out.println(blog4);
session2.commit();
System.out.println(blog1==blog2);
}
使用debug方式执行:
发现blog1和blog2 的引用相同,但是blog3和blog4的引用并不同。
原因: 因为blog2是从一级缓存中取出的,所以和blog1 的值相同,在sqlsession1 使用了commit()方法之后,该对象被序列化到二级缓存中了,blog3是从二级缓存中反序列化得到的对象,blog4也是反序列化得到的对象,得到的不是原实例,而是原实例的拷贝
而且观察控制台可以发现,我们的select语句只查询了一次:
所以二级缓存产生了效果



