Mybatis延迟加载(懒加载)

一、什么是延迟加载

将采用高级映射实现多表联查时向数据库发出的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());
		}
}
测试结果

另外附上表关系图及全局配置文件


Mybatis-config.xml配置

<?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>



猜你喜欢

转载自blog.csdn.net/jinYwuM/article/details/80445897
今日推荐