在上一篇博客 Mybatis框架之快速入门(别再翻了,此篇博客就够了) 介绍了Mybatis框架基本使用细节,在本篇博客将介绍一下延时加载与查询缓存相关内容。
一、延时加载
延时加载
,当用到的时候再去访问数据库加载数据,也称为懒加载
。
此加载策略默认是不开启的,需要手动开启。
1、懒加载开启方法:
在Mybatis主配置文件中添加lazyLoadingEnabled
即可。
测试示例:
懒加载示例实体类之间的关系,一个OrderItem对象包含一个Product对象,一个Order对象包含多个OrderItem对象。关于示例的更新细节,请参考我的另外一篇博客 Mybatis框架之实体之间的关系处理(关联查询)(附Demo:用户和订单)
测试源码:
package cn.hestyle.test;
import cn.hestyle.entity.Order;
import cn.hestyle.entity.OrderItem;
import cn.hestyle.mapper.OrderMapper;
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.Test;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
/**
* description: 懒加载测试
*
* @author hestyle
* @version 1.0
* @className mybatis_day_01->LazyLoadingTest
* @date 2020-01-26 19:20
**/
public class LazyLoadingTest {
private static InputStream inputStream;
private static SqlSessionFactory sqlSessionFactory;
private static SqlSession sqlSession;
private static OrderMapper orderMapper;
static {
try {
//读取Mybatis配置文件
inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
//创建sqlSessionFactory,然后获取sqlSession
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
sqlSession = sqlSessionFactory.openSession();
orderMapper = sqlSession.getMapper(OrderMapper.class);
} catch (IOException e) {
e.printStackTrace();
}
}
@Test
public void testLazyLoading() throws IOException {
//查找所有的order
List<Order> orderList = orderMapper.findAll();
for (Order order : orderList) {
System.err.println("=========================分割线===========================");
System.err.println(order);
for (OrderItem orderItem : order.getOrderItemList()) {
System.err.println(orderItem);
}
}
sqlSession.close();
}
}
2、立即加载(默认)
3、懒加载(手动配置)
两张图就是SQL执行与打印结果顺序不同,懒加载是用到的时候再去访问数据库。
4、注意
在mybatis中,resultMap
标签 的association
标签和collection
标签才具有延迟加载的功能。
二、查询缓存
所谓Mybatis查询缓存
,就是当我们从数据库查找出数据时,Mybatis
会将查询结果在内存中做一个暂存。当我们再次查找数据时,它会自动去查找缓存内有没有需要查找的结果,如果在缓存中查找到了,则直接从缓存中取,否则再去访问数据库查找需要的数据。看下面的示例就懂了什么是查询缓存。
Mybatis查询缓存
根据作用的范围又可以分成一级缓存
、二级缓存
。
1、一级缓存
此缓存
,缓存范围是同一个SqlSession
,即同一个SqlSession
查找到的结果可共享。
同一个SqlSession
每次进行查找数据时,默认暂存到一个共同的位置,当此SqlSession
进行数据插入
、更新
、删除
、事务提交
、SqlSession关闭
时,缓存内容清空。
2、二级缓存
此缓存
,缓存的范围是整个SqlSessionFactory
,同一个SqlSessionFactory
生成的所有SqlSession
都共享。
一级缓存与二级缓存之间的关系。
①、二级缓存开启方式
在Mybatis主配置文件中配置
在需要开启二级缓存的mapper命名空间中配置
在需要开启二级缓存的实体类实现序列化接口
②、二级缓存效果
package cn.hestyle.test;
import cn.hestyle.entity.User;
import cn.hestyle.mapper.UserMapper;
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.Test;
import java.io.IOException;
import java.io.InputStream;
/**
* description: 缓存测试
*
* @author hestyle
* @version 1.0
* @className mybatis_day_01->CashTest
* @date 2020-01-26 19:42
**/
public class CashTest {
private static InputStream inputStream;
private static SqlSessionFactory sqlSessionFactory;
static {
try {
//读取Mybatis配置文件
inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
//创建sqlSessionFactory,然后获取sqlSession
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
@Test
public void testCash(){
SqlSession sqlSession1 = sqlSessionFactory.openSession();
UserMapper userMapper1 = sqlSession1.getMapper(UserMapper.class);
SqlSession sqlSession2 = sqlSessionFactory.openSession();
UserMapper userMapper2 = sqlSession2.getMapper(UserMapper.class);
User user1 = userMapper1.findUserById(1);
System.err.println(user1);
System.err.println("=================分割线=================");
//两个SqlSession来自于同一个sqlSessionFactory,按道理存在二级缓存,不用再次访问数据库
User user2 = userMapper2.findUserById(1);
System.err.println(user2);
sqlSession1.close();
sqlSession2.close();
}
}
控制天输出结果:
默认缓存只有一级缓存,只有开启了二级缓存、并且响应的SqlSession进行了事务提交、关闭,该SqlSession产生的一级缓存内容才会转化为同一个SqlSessionFactory的二级缓存。
package cn.hestyle.test;
import cn.hestyle.entity.User;
import cn.hestyle.mapper.UserMapper;
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.Test;
import java.io.IOException;
import java.io.InputStream;
/**
* description: 缓存测试
*
* @author hestyle
* @version 1.0
* @className mybatis_day_01->CashTest
* @date 2020-01-26 19:42
**/
public class CashTest {
private static InputStream inputStream;
private static SqlSessionFactory sqlSessionFactory;
static {
try {
//读取Mybatis配置文件
inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
//创建sqlSessionFactory,然后获取sqlSession
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
@Test
public void testCash(){
SqlSession sqlSession1 = sqlSessionFactory.openSession();
UserMapper userMapper1 = sqlSession1.getMapper(UserMapper.class);
SqlSession sqlSession2 = sqlSessionFactory.openSession();
UserMapper userMapper2 = sqlSession2.getMapper(UserMapper.class);
User user1 = userMapper1.findUserById(1);
System.err.println(user1);
sqlSession1.commit();
System.err.println("=================分割线=================");
//两个SqlSession来自于同一个sqlSessionFactory,
//并且SqlSession1进行了提交、UserMapper开启了二级缓存,不用再次访问数据库
User user2 = userMapper2.findUserById(1);
System.err.println(user2);
sqlSession1.close();
sqlSession2.close();
}
}
控制台输出结果:
与一级缓存一样,如果SqlSessionFactory中的某个SqlSession进行了数据插入、删除、修改,整个二级缓存同样会进行清空。
package cn.hestyle.test;
import cn.hestyle.entity.User;
import cn.hestyle.mapper.UserMapper;
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.Test;
import java.io.IOException;
import java.io.InputStream;
/**
* description: 缓存测试
*
* @author hestyle
* @version 1.0
* @className mybatis_day_01->CashTest
* @date 2020-01-26 19:42
**/
public class CashTest {
private static InputStream inputStream;
private static SqlSessionFactory sqlSessionFactory;
static {
try {
//读取Mybatis配置文件
inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
//创建sqlSessionFactory,然后获取sqlSession
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
@Test
public void testCash(){
SqlSession sqlSession1 = sqlSessionFactory.openSession();
UserMapper userMapper1 = sqlSession1.getMapper(UserMapper.class);
SqlSession sqlSession2 = sqlSessionFactory.openSession();
UserMapper userMapper2 = sqlSession2.getMapper(UserMapper.class);
User user1 = userMapper1.findUserById(1);
System.err.println(user1);
sqlSession1.commit();
System.err.println("=================分割线=================");
//两个SqlSession来自于同一个sqlSessionFactory,
//并且SqlSession1进行了提交、UserMapper开启了二级缓存,不用再次访问数据库
user1.setUsername("hestyle-修改-修改");
userMapper1.update(user1);
sqlSession1.commit();
//但是由于sqlSession1进行了数据更新,整个SqlSessionFactory的二级缓存全部被清空
User user2 = userMapper2.findUserById(1);
System.err.println(user2);
sqlSession1.close();
sqlSession2.close();
}
}
以上就是Mybatis框架中的延时加载与查询缓存的主要内容,顺带一提,查询缓存主要用于对数据响应速度高,并且数据不怎么修改的场景,否则频繁创建、清空缓存,效率会大大降低。