一、为什么要使用延迟加载?
-
使用延迟加载的意义
在进行数据查询时,为了提高数据库查询性能,尽量使用单表查询,因为单表查询比多表关联查询速度快。
如果查询单表就可以满足需求,一开始先查询单表,当需要关联信息时,再关联查询。当需要关联信息时才进行查询就叫做延迟加载。mybatis中resultMap提供延迟加载功能,通过resultMap配置延迟加载。
在mybatis-config.xml中配置全局参数
<!-- 全局配置参数 --> <settings> <!-- 延迟加载总开关 --> <setting name="lazyLoadingEnabled" value="true"/> <!-- 设置按需加载 --> <setting name="aggressiveLazyLoading" value="false"/> </settings>
二、案例
- 需求:查询订单并且关联查询消费者信息,要求只有使用到消费者信息的时候才发送查询用户信息的sql语句。
2.1 创建数据库表和实体对象
Customer.java
package com.shyroke.entity; public class Customer { private int user_id; private String user_name; private String user_sex; private String user_birthday; //隐藏get和set方法 }
Order.java
package com.shyroke.entity; public class Orders { private int order_id; private String order_number; private String order_createTime; private String order_note; private String user_id; //消费者信息,为了保存查询得到的关联的User表的信息(一对一) private Customer customer; //隐藏get和set方法 }
2.2 创建OrderMapper.java接口和 OrderMapper.xml配置文件
OrderMapper.java
package com.shyroke.mapper; import java.util.List; import com.shyroke.entity.Orders; public interface OrderMapper { public List<Orders> selectOrderByLazyLoading(); }
OrderMapper.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.shyroke.mapper.OrderMapper"> <resultMap type="com.shyroke.entity.Customer" id="customerMap"> <id column="user_id" property="user_id"/> <result column="user_name" property="user_name"/> <result column="user_sex" property="user_sex"/> <result column="user_birthday" property="user_birthday"/> </resultMap> <resultMap type="com.shyroke.entity.Orders" id="orderByLazyLoading"> <id column="order_id" property="order_id"/> <result column="order_number" property="order_number"/> <result column="order_createTime" property="order_createTime"/> <result column="order_note" property="order_note"/> <result column="user_id" property="user_id"/> <association property="customer" select="findCustomerById" column="user_id"></association> </resultMap> <select id="findCustomerById" parameterType="int" resultMap="customerMap"> SELECT * FROM CUSTOMER WHERE user_id=#{value} </select> <select id="selectOrderByLazyLoading" resultMap="orderByLazyLoading"> SELECT * FROM orders </select> </mapper>
- association标签中的select属性:延迟加载执行的sql所在的statement的id,如果不在同一个namespace需要加namespace 。
sql:根据用户id查询消费者信息 column:关联查询的列
property:将关联查询的用户信息设置到Orders的哪个属性
- 整个流程大概为:当需要用到消费者信息时才会发送association标签中select="findCustomerById"对应的select标签中id=“findCustomerById”的sql语句。
2.3 在总配置文件中打开延迟加载的开启
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <settings>
<!--开启延迟加载-->
<setting name="lazyLoadingEnabled" value="true"/> <setting name="aggressiveLazyLoading" value="false"/> </settings> <environments default="development"> <environment id="development"> <transactionManager type="JDBC" /> <!-- 配置数据库连接信息 --> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver" /> <property name="url" value="jdbc:mysql://localhost:3306/test?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC" /> <property name="username" value="root" /> <property name="password" value="" /> </dataSource> </environment> </environments> <mappers> <package name="com.shyroke.mapper"/> </mappers> </configuration>
2.4 测试
package com.shyrolk.firstMybatis; import java.io.IOException; import java.io.InputStream; import java.util.List; 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 com.shyroke.entity.Orders; import com.shyroke.mapper.OrderMapper; /** * Hello world! * */ public class App { public static void main(String[] args) throws IOException { String resource = "resource/mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream); SqlSession session = sessionFactory.openSession(); OrderMapper orderMapper = session.getMapper(OrderMapper.class); List<Orders> orderList = orderMapper.selectOrderByLazyLoading(); System.out.println(orderList.get(0).getOrder_id()); } }
结果:
-
一对多查询延迟加载
一对多延迟加载的方法同一对一延迟加载,在collection标签中配置select内容。