为什么使用缓存?
mybatis的缓存机制是为了减少数据库的压力,提高整体性能。一般mybatis读取数据是从数据库获取,也就是从硬盘上获取的,若是在短时间内有大量访问,那么时常会出现卡顿,而从内存读取相对从硬盘上读取效率快,因此就出现了内存读取的mybatis缓存机制。
Mybatis缓存概念:
Mybatis缓存分为一级缓存和二级缓存
一级缓存:
是SqlSession级别的,在同一个SqlSession中相同的多次查询,只查询数据库一次 将第一次查询的数据存储到SqlSession对象中,第二次直接从SqlSession对象中获取即可
二级缓存:
二级缓存是SqlSessionFactory级别的,根据mapper的namespace划分区域的,相同namespace的mapper查询的数据缓存在同一个区域。
实操分析:
一级缓存
我们使用同一个SqlSession对象调用一个Mapper方法,往往只执行一次SQL,因为使用SelSession第一次查询后,MyBatis会将其放在缓存中。
Dao:
public interface StudentDao {
Student findStudentById1(int id);
}
public class Test6 {
public static void main(String[] args) throws IOException {
SqlSession sqlSession= MybatisUtil.getSqlSession();
StudentDao studentDao=sqlSession.getMapper(StudentDao.class);
studentDao.findStudentById1(1);
studentDao.findStudentById1(1);
sqlSession.close();
}
}
上述代码使用同一个SqlSession调用了两次同一Mapper方法
日志中,只与数据库进行了一次交互。
sqlSession.clearCache();强制清空一级缓存
public class Test6 {
public static void main(String[] args) throws IOException {
SqlSession sqlSession= MybatisUtil.getSqlSession();
StudentDao studentDao=sqlSession.getMapper(StudentDao.class);
studentDao.findStudentById1(1);
sqlSession.clearCache(); //强制清空一级缓存*/
studentDao.findStudentById1(1);
sqlSession.close();
}
}
在第一次与数据库交互后,内存中已经有了记录,但是使用 clearCache()强制清空缓存后,内存记中所有记录清空,再次进行同一个查询语句时需要再次向数据库索取。java中不建议使用,因为是强制的,所以有可能会导致文件损坏。
二级缓存
使用需要配置:
1.在SqlMapperConfig.xml中启用二级缓存,如下代码所示
<setting name="cacheEnabled" value="true"/>
当cacheEnabled设置为true时启用二级缓存,设置为false时禁用二级缓存。
2.将所有的POJO类实现序列化接口Java.io.Serializable。
public class Student implements Serializable{
}
3.在Mapper映射文件中添加<cache/>,表示此mapper开启二级缓存。当SqlSeesion关闭时,会将数据存入到二级缓存.
<cache size="20" flushInterval="3000"></cache>
'3000'表示持续时间,超过时间后清空二级缓存。
public static void main(String[] args) throws IOException {
//创建SqlSessionFactory对象
SqlSession sqlSession= MybatisUtil.getSqlSession();
StudentDao studentDao= sqlSession.getMapper(StudentDao.class);
studentDao.findStudentById1(5);
sqlSession.close();
SqlSession sqlSession1= MybatisUtil.getSqlSession();
StudentDao studentDao1= sqlSession1.getMapper(StudentDao.class);
studentDao1.findStudentById1(5);
sqlSession1.close();
}
上述代码创建了两次SqlSession,每次使用完都会关闭,而日志只打印一次,说明只有第一次执行了一次SQL,第二次是在内存中缓存获取。