一、什么是延迟加载
将采用高级映射实现多表联查时向数据库发出的SQL语句拆分成若干条单表查询的SQL语句,当需要返回数据时才会向数据库发出只针对当前数据的SQL语句。
1、延迟加载的条件:
使用resultMap高级映射(主要体现在与元素association、collection实现一对一及一对多映射上),association、collection具备分层查询的功能,间接具备了实现延迟加载的属性。
2、延迟加载的好处:
先从单表查询、需要时再从关联表去关联查询,提升数据库性能,因为查询单表要比关联查询多张表速度要快,内存资源占用更少。但是很少使用,内存不够就加内存,毕竟能用钱解决的事情就别烧脑。
二、延迟加载的实例:
需求:根据订单编号,查询订单,并返回订单详情描述信息将需求拆分成三部分,查询订单并且关联查询用户信息及订单详情。如果值查询订单信息即可满足要求,那么只发送查询订单信息的SQL语句;当我们需要查询用户信息,且需要查看用户信息时,只需要再分别发送查询订单信息和用户信息的SQL语句;当用户需要查看所有信息时,在之前的查询结果基础上,追加发出一条查询订单详情的SQL语句,在这里用户信息的按需查询就是延迟加载。
实现延迟加载的前提条件
在settings中配置与延迟加载有关的属性.
<settings>
<!-- 开启延迟加载 -->
<setting name="lazyLoadingEnabled" value="true" />
<setting name="aggressiveLazyLoading" value="false" />
</settings>
下面是XML的映射文件LazyLoadingMapper.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.the.one.mapper.OrderMapper">
<!-- 高级映射查询,将查询到的结果封装到Order对象中 -->
<resultMap type="Order" id="orderUserLazyMap" autoMapping="true">
<id column="id" property="id" />
<!-- 关联查询user select:延迟加载user,通过association元素中的select属性选择第二条查询语句进行发送
column:查询user的参数,该id的信息其实是在查询出来的order中的user_id -->
<association property="user" javaType="User"
select="queryUserByUserIdOfOrder" column="{id=user_id}" autoMapping="true">
</association>
<!-- 关联查询orderdetail select:
延迟加载orderdetail,通过collection元素中的select属性选择第三条查询语句进行发送
column:id指的是order表中的主键,对应orderdetail中的order_id -->
<collection property="orderdetail" javaType="List" ofType="Orderdetail"
select="queryOrderdetailByOrderNumberOfOrder" column="{id=id}"
autoMapping="true">
</collection>
</resultMap>
<!-- 通过order_number查询order -->
<select id="queryOrderUserLazy" resultMap="orderUserLazyMap">
select * from tb_order where order_number = #{orderNumber}
</select>
<!-- 通过order中的user_id查询user -->
<select id="queryUserByUserIdOfOrder" resultType="User">
select * from tb_user where id = #{id}
</select>
<!-- 通过order中的id查询orderdetail -->
<select id="queryOrderdetailByOrderNumberOfOrder" resultType="Orderdetail">
select * from tb_orderdetail where order_id = #{id}
</select>
</mapper>
注意两点:
1、元素association、collection中的colunm属性,如果传递的参数只有一个,直接使用user_id即可,如果是多个可以使用{user_id=id,user_nam=userName}来传递。
2、resultType属性:若查询结果是集合,那应该是集合可以包含的类型,而不能是集合本身。使用 resultType 或 resultMap,但不能同时使用。
public interface OrderMapper {
Order queryOrderUserLazy(@Param("orderNumber") String orderNumber);
}
测试代码
public class OrderMapperTest {
private OrderMapper orderMapper;
@Before
public void setUp() throws Exception {
InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory build = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession openSession = build.openSession(true);
orderMapper = openSession.getMapper(OrderMapper.class);
}
// <!-- 根据20140921001订单号查询出订单信息,下单人信息,以及查询出订单详情,采用延迟加载 -->
@Test
public void testQueryOrderUserLazy() {
Order order = orderMapper.queryOrderUserLazy("20140921001");
System.out.println(order.getOrderNumber());
System.out.println(order.getUser());
System.out.println(order.getOrderdetail());
}
}
测试结果
另外附上表关系图及全局配置文件
<?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>
<properties resource="jdbc.properties"></properties>
<settings>
<!-- 开启自动映射 -->
<!-- <setting name="autoMappingBehavior" value="FULL" /> -->
<!-- 设置驼峰参数 -->
<setting name="mapUnderscoreToCamelCase" value="true" />
<!-- 关闭二级缓存,默认是开启,false:关闭 -->
<setting name="cacheEnabled" value="false" />
<!-- 开启延迟加载 -->
<setting name="lazyLoadingEnabled" value="true" />
<setting name="aggressiveLazyLoading" value="false" />
</settings>
<typeAliases>
<package name="com.the.one.pojo" />
</typeAliases>
<environments default="develop">
<environment id="develop">
<transactionManager type="JDBC"></transactionManager>
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driverClass}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="UserMapper.xml" />
<mapper resource="CommonSql.xml" />
<mapper resource="OrderMapper.xml" />
<mapper resource="OrderUserMapper.xml" />
<mapper resource="LazyLoadingMapper.xml" />
</mappers>
</configuration>