延迟加载与按需加载
例:一张订单表,表里面有用户id字段,当执行查询订单时,可能需要根据用户id查询用户信息,也可能不需要。因此可对查询用户信息实行延迟加载。当没有获取用户信息的操作出现时,即不执行用户信息查询。
这里即将两个sql语句分开执行
1. 设置
默认设置:
<settings> <setting name="lazyLoadingEnabled" value="false"/> <setting name="aggressiveLazyLoading" value="true"/> </settings>
lazyLoadingEnable:是否启用延迟加载
aggressiveLazyLoading:是否按需加载属性。为false时,当启用延迟加载时,只要加载对象,就加载对象的所有属性
真正需要的是按需加载:延迟加载开启(lazyLoadingEnabled为true),且按需加载开启(aggressiveLazyLoading为false)
若延迟加载关闭,则按需加载无论开启还是关闭,一开始所有sql都会执行
2. 测试
2.1 准备两张表
//测试mybatis延迟加载 create table orders(id int primary key, user_id int, createtime timestamp default current_timestamp, note varchar(20) ); create table users(id int primary key auto_increment, name varchar(20), age int, sex varchar(10), money double );
表orders有 user_id 字段,通过此字段可以去查询uses表获取user信息
2.2 实体类
Order.java(表orders有4个字段,但实体类有第五个属性,这第五个属性即是展现延迟加载的地方)
public class Order { private int id; private int userId; private Date createTime; private String note; private User userInfo; getter、setter toString() }
User.java
public class User { private int id; private String name; private int age; private String sex; Double money; getter、setter }
延迟加载说明:当我们查询orders里面的信息,映射到Order实体类上时,如果不需要根据Order的 userInfo 字段去获取User信息,则不执行查询User的操作;当需要时才去执行
2.3 OrderDao、UserDao以及他们的映射文件
OrderDao.java
public interface OrderDao { /*查询订单信息*/ List<Order> findAllOrders(); }
OrderDao.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.xt.dao.OrderDao"> <!--配置查询所有--> <select id="findAllOrders" resultMap="orderInfoResMap"> select * from orders </select> <resultMap type="com.xt.domain.Order" id="orderInfoResMap"> <id column="id" property="id"/> <result column="user_id" property="userId"/> <result column="createtime" property="createTime"/> <result column="note" property="note"/> <association property="userInfo" select="com.xt.dao.UserDao.findUserById" column="user_id"></association> <!--按需加载的地方--> </resultMap> </mapper>
UserDao.java
public interface UserDao { /*根据订单id查询*/ User findUserById(int id); }
UserDao.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.xt.dao.UserDao"> <select id="findUserById" parameterType="int" resultType="com.xt.domain.User"> select * from users where id = #{id} </select> </mapper>
2.4 测试
(1)开启延迟加载,开启按需加载
<setting name="lazyLoadingEnabled" value="true"/> <setting name="aggressiveLazyLoading" value="false"/>
InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml"); SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is); SqlSession session = factory.openSession(); OrderDao orderDao = session.getMapper(OrderDao.class); //通过代理对象调用方法 List<Order> allOrders = orderDao.findAllOrders(); Order order = allOrders.get(0); String note = order.getNote(); //String name = order.getUserInfo().getName(); session.close(); is.close();
测试结果:因为没有调用 getUserInfo(),则就不需要根据order里面的user_id 去查询用户信息了,mybatis日志输出发现只执行了查询orders表的sql
如果执行 getUserInfo,则会执行根据 user_id 查询 users 表的sql
(2)开启延迟加载,关闭按需加载
关闭了按需加载,则只要去获取Order的某个属性,所有的属性都会加载(包括本来要延迟加载的 userInfo 字段信息)
<setting name="lazyLoadingEnabled" value="true"/> <setting name="aggressiveLazyLoading" value="true"/>
测试代码同上,但当执行到 getNote() 时,第二个sql(根据 user_id 去查第二张表)也会执行
原文:https://www.cnblogs.com/taoXiang/p/13174961.html