作用
- 当对某些数据的查询请求频繁,且数据不经常修改时,使用缓存机制可以提高查询效率
注意
- mybatis专注于sql查询,数据映射
- 缓存问题应该交给专门负责缓存的其他第三方框架
mybatis缓存执行流程
mybatis一级和二级缓存
- 一级缓存作用域:sqlSession对象
- 二级缓存作用域:Mapper.xml文件
- 查询顺序:先二级缓存,再一级缓存,最后查数据库
mybatis一级缓存
一级缓存测试
package com.example.mapper;
import com.example.pojo.User;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
public class TestUsersMapper {
SqlSession sqlSession;
UsersMapper usersMapper;
@Before
public void getSqlSession() throws IOException {
InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
sqlSession = factory.openSession();
usersMapper = sqlSession.getMapper(UsersMapper.class);
}
@After
public void closeSession(){
sqlSession.close();
}
@Test
public void testOneLevelCache(){
User u1 = usersMapper.getById(1);
System.out.println("第1次查询结果: " + u1);
System.out.println("----------------------");
User u2 = usersMapper.getById(1);
System.out.println("第2次查询结果: " + u2);
System.out.println("------------------------");
if(u1 == u2){
System.out.println("两个对象的内存地址相同");
}else{
System.out.println("两个对象的内存地址不同");
}
System.out.println("**************************************************");
User u3 = usersMapper.getById(2);
System.out.println("第1次查询结果: " + u3);
System.out.println("----------------------");
User u4 = usersMapper.getById(5);
System.out.println("第2次查询结果: " + u4);
System.out.println("------------------------");
if(u3 == u4){
System.out.println("两个对象的内存地址相同");
}else{
System.out.println("两个对象的内存地址不同");
}
}
}
测试结果
==> Preparing: select id, username, birthday, sex, address from users where id=?
==> Parameters: 1(Integer)
<== Columns: id, username, birthday, sex, address
<== Row: 1, 荷包蛋, 2002-08-23, 女, 黑河
<== Total: 1
第1次查询结果: Users{id=1, userName='荷包蛋', birthday=Fri Aug 23 00:00:00 CST 2002, sex='女', address='黑河'}
----------------------
第2次查询结果: Users{id=1, userName='荷包蛋', birthday=Fri Aug 23 00:00:00 CST 2002, sex='女', address='黑河'}
------------------------
两个对象的内存地址相同
**************************************************
==> Preparing: select id, username, birthday, sex, address from users where id=?
==> Parameters: 2(Integer)
<== Columns: id, username, birthday, sex, address
<== Row: 2, 小王, 2001-07-12, 1, 芜湖市
<== Total: 1
第1次查询结果: Users{id=2, userName='小王', birthday=Thu Jul 12 00:00:00 CST 2001, sex='1', address='芜湖市'}
----------------------
==> Preparing: select id, username, birthday, sex, address from users where id=?
==> Parameters: 5(Integer)
<== Columns: id, username, birthday, sex, address
<== Row: 5, 段, 2001-03-10, 1, 太原
<== Total: 1
第2次查询结果: Users{id=5, userName='段', birthday=Sat Mar 10 00:00:00 CST 2001, sex='1', address='太原'}
------------------------
两个对象的内存地址不同
结果分析
- 以上u1到u4同属于一个sqlSession域,因为下面代码只执行过一次,sqlSession只获取过一个,后面操作都是在该sqlSession对象的基础上进行的
sqlSession = factory.openSession();
- 当两次查询的id相同时,第一次查询开启了数据库连接,第二次没有再开启数据库连接,而是从缓存中获取,且两个对象内存地址相同
- 其实u1和u2本质上是sqlSession域中的同一个对象
- 当两次查询的id不同时,两次查询都开启了数据库连接,且两个对象内存地址不同
- 其实u3和u4本质上是sqlSession域中的不同对象