MyBatis——第3章 关联关系查询(二)

3.2 延迟加载

       MyBatis 中的延迟加载,也成为懒加载,是指在进行关联查询时,按照设置规则推迟对关联对象的select查询,延迟加载能有效地减小数据库的压力。

仅仅对关联对象的select查询进行延迟,对于主加载对象都是直接执行查询语句的。

<?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.bjpowernode.dao.INewsLabelDao">

关联查询-延迟加载
<select id="selectNewslabelByParent" resultMap="newsLabelMapper">
	select id,name from newslabel where pid = #{id}
</select>


<resultMap type="Newslabel" id="newsLabelMapper">
	<id column="id" property="id"/>
	<result column="name" property="name"/>
	<collection property="children" 
				ofType="NewsLabel"
				select="selectNewslabelByParent"
				column="id"/>
</resultMap>

主查询- 直接加载 
<select id="selectNewsLabelById" resultMap="newslabelMapper">
	select id,name from newslabel where id=#{id}
</select>
	
</mapper>

3.2.1 关联对象加载时机

直接加载:多表连接查询就是直接加载,无法延迟加载。

侵入式延迟:对主加载对象详情的查询会直接引起对关联加载的查询。

深度延迟:需要访问关联对象的时候再去查。

设置如下:

	<!--设置整个应用所使用的常量值 -->
	<settings>
		<!--延迟加载的总开关 -->
		<setting name="LazyLoadingEnable" value="true"/>
		<!--侵入式延迟加载开关  -->
		<setting name="aggressiveLazyLoading" value="false"/>
	</settings>
	@Test
	public void test01(){
		Country country = dao.selectCountryById(2);
		System.out.println(country.getCname());
		Set<Minister> ministers = country.getMinisters();
		System.out.println(ministers.size());
	}

今日内容总结:

Mapper动态代理:

     ①:保证sql id和接口名方法名重名

     ②:namespace名 改成接口的全名 

     ③:调用dao = sqlSession.getMapper(...接口dao.class)

动态SQL:

    解决查询条件不固定,可以动态组合

关联查询:

   

<think>嗯,用户这次询问的是MyBatis-Plus是否支持多表查询,看来ta在开发中遇到了复杂查询的需求。从对话历史看,用户之前询问过“过期”的英文翻译,突然转向技术问题,可能是不同场景下的需求切换。 用户提供的四个引用很有价值:引用[1][2]介绍了mybatis-plus-join这个第三方扩展,引用[3]展示了原生MyBatis的注解实现方式,引用[4]则涉及多数据源配置。不过用户特别强调“上述引用仅供参考”,说明ta更MyBatis-Plus原生能力。 需要明确告知用户核心事实:MyBatis-Plus本身专注单表操作,确实不直接支持查询。但解决方案分三个层次:第一层是用原生MyBatis的XML/注解写SQL(引用[3]示例),第层是借助Wrapper的apply方法拼接SQL片段(最灵活但需手写部分SQL),第三层才是集成第三方插件如mybatis-plus-join(引用[1][2])。 用户可能是中级开发者——既知道MyBatis-Plus的基础能力,又面临复杂业务查询的困境。ta没提具体业务场景,但“查询”这个键词暗示涉及主子表或数据聚合。在回答时要强调“根据复杂度选择方案”:简单联用Wrapper.apply,复杂场景用原生SQL或插件。 安全提示不能少:第三方插件虽方便,但需评估项目风险,尤其引用[2]的GitHub项目才200+star,生产环境要谨慎。最后生成的三个相问题都直击痛点:查询的性能优化(用户可能遇到慢查询)、Wrapper的边界(用户可能想避免手写SQL)、多表分页(实际开发高频需求)。</think>根据技术文档和社区实践,MyBatis-Plus **原生不支持多表查询**,但可通过以下方案实现: ### 一、原生MyBatis-Plus的局限性 1. **设计定位** MyBatis-Plus 核心定位是**单表操作增强**,其内置的 `Wrapper` 仅支持单表条件构造[^1][^2]。 2. **官方说明** 官方文档明确表示:多表查询需**回归原生MyBatis的XML或注解方式**实现[^3]。 --- ### 、实现查询的三种方案 #### 方案1:原生MyBatis实现(推荐) ```java // 1. 注解方式(引用[3]示例) @Select("SELECT u.*, o.order_no FROM user u LEFT JOIN order o ON u.id = o.user_id") List<Map<String, Object>> selectUserWithOrders(); // 2. XML方式 <!-- UserMapper.xml --> <select id="selectJoinData" resultType="map"> SELECT u.name, o.total FROM user u JOIN orders o ON u.id = o.user_id </select> ``` #### 方案2:使用Wrapper的`apply()`拼接SQL片段 ```java // 手动拼接联条件(有限度支持) QueryWrapper<User> wrapper = new QueryWrapper<>(); wrapper.apply("EXISTS (SELECT 1 FROM orders o WHERE o.user_id = user.id AND o.status=1)"); userMapper.selectList(wrapper); ``` > ⚠️ 仅适用于简单联,复杂联仍需完整SQL #### 方案3:集成第三方插件 1. **mybatis-plus-join**(引用[1][2]) ```java // 示例:两表查询 List<UserOrderVO> list = userMapper.selectJoinList(JoinWrapper.<User>create() .leftJoin(Order.class, Order::getUserId, User::getId) .selectAs(User::getName, "userName") .select(Order::getOrderNo)); ``` - 特性:链式API/自动映射/避免手写SQL - GitHub:https://github.com/nullbull/mybatis-plus-join 2. **mybatis-plus-extension**等插件 需注意社区插件的**稳定性评估**和生产风险 --- ### 三、方案对比 | 方案 | 开发效率 | 灵活性 | 学习成本 | 适用场景 | |---------------------|----------|--------|----------|-----------------------| | 原生MyBatis | ★★☆ | ★★★★★ | ★★★ | 复杂联/复杂聚合查询 | | Wrapper.apply() | ★★★ | ★★☆ | ★★ | 简单子查询/EXISTS条件 | | 第三方插件 | ★★★★★ | ★★★☆ | ★★☆ | 快速开发中等复杂度联 | --- ### 结论 1. **常规场景**:优先使用**原生MyBatis的XML/注解**实现查询(方案1) 2. **简单子查询**:可尝试 `Wrapper.apply()`(方案2) 3. **快速开发**:评估稳定性后选择 **mybatis-plus-join** 等插件(方案3) > 📌 键建议:**超过两表联或含聚合操作时,务必使用原生SQL保证可维护性**。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值