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

本文详细解析了MyBatis中的一对多、多对一、自关联及多对多关联查询方法,包括多表连接查询和延迟加载两种方式,并通过具体示例展示了如何使用XML配置实现这些查询。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

外键肯定定义在多方表,有外键肯定充当在多方的。

3.1.1 一对多关联查询

一方可以看见多方,这里的一对多查询是指,在查询一方对象的时候,同时也将其关联的多方对象也都查询出来。

方式一:多表连接查询

<?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.ICountryDao">
	
	<resultMap type="Country" id="countryMapper">
		<id column="cid" property="cid"/>
		<result column="cname" property="cname"/>
		<collection property="minsters" ofType="Minister">
			<id column="mid" property="mid"/>
			<result column="mname" property="mname"/>
		</collection>
	</resultMap>
	
	<select id="selectCountryById" resultMap="countryMapper">
		select cid,cname,mid,mname
		from country,minister
		where cid = countryId 
		and cid = #{id} 
	</select>
</mapper>

  方式二:多表单独查询方式(用的比较多,延迟查询)

<?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.IStudentDao">

	<select id="selectMinisterByCountry" resultType="Minister">
		select mid,mname by minister where mid = #{cid}
	</select>
	
	<resultMap type="Country" id="CountryMapper">
		<id column="cid" property="cid"/>
		<result column="cname" property="cname"/>
		<collection property="ministers" 
			    ofType="Minister"
			    select="selectMinisterByCountry"
			    column="cid"/>
	</resultMap>
	
	<select id="selectCountryById" resultMap="CountryMapper">
		select cid,cname from country where cid = 2
	</select>
</mapper>

<resultMap>:映射信息

     type:所选的类名(一对多中一代表的类名)

     <id>:  代表主键 

                column:表中字段

                property:类中属性

     <result> 其他键(属性)

     <collection> 一对多中的多

                property:代表一对多中的多的属性

                ofType:集合 集合成的类名

                select :单独查询的另一个选择

                column:两个单独查询的相交点(关联属性)

3.1.2 多对一查询

方式一:多表连接查询

<?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.IMinisterDao">

	<resultMap type="minister" id="ministerMapper">
		<id column="mid" property="mid"/>
		<result column="mname" property="mname"/>
		<association property="country" javaType="Country">
			<id column="cid" property="cid"/>
			<result column="cname" property="cname"/>
		</association>
	</resultMap>

	<select id="selectMinisterById" resultMap="ministerMapper">
		select mid,mname,cid,cname
		from minister,country
		where cid = countryId
		and mid = #{mid}
	</select>
	
</mapper>

 多对一的<association> 类比一对多的<collection>

 <assciation property="多对一中一的属性",javatype=“l类比ofType 属性对应的类”/>

方式二:多表单独查询

<?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.IMinisterDao">

	<select id="selectCountryById" resultMap="Country">
		select cid,cname from country where cid = #{countryId}
	</select>

	<resultMap type="minister" id="ministerMapper">
		<id column="mid" property="mid"/>
		<result column="mname" property="mname"/>
		<association property="country"
					 javaType="Country"
					 select="selectCountryById"
					 column="countryId"
					 />

	</resultMap>

	<select id="selectMinisterById" resultMap="ministerMapper">
		select mid,mname
		from minister
		where mid = #{mid}
	</select>
	
</mapper>

关键是column=“countryId” 找到两个查询之间的关联点。

3.1.3 自关联查询

(1)以一对多方式处理

A、查询指定栏目的所有子孙栏目

    递归调用

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

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

<select id="selectChildrenByParent" resultMap="newslabelMapper">
	select id,name from newslabel where pid=#{id}
</select>
	
</mapper>

B、查询指定栏目及其所有子孙栏目

 

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

(2)以多对一方式来处理

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


<resultMap type="NewsLabel" id="newslabelMapping">
	<id column="id" property="id"/>
	<result column="name" property="name"/>
	<association property="parent"
		javaType="NewsLabel"
		select ="selectNewsLabelById"
		column="pid"/>
</resultMap>


<select id="selectNewsLabelById" resultMap="newslabelMapping">
	select id,name,pid from newslabel where id = #{pid}
</select>
	
</mapper>

3.1.4 多对多关联查询

两个一对多构成的

中间件middle为多,student和course为一

<?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.IStudentDao">


<resultMap type="Student" id="studentMapping">
	<id column="sid" property="sid"/>
	<result column="sname" property="sname"/>
	<collection property="courses" ofType="Course">
		<id column="cid" property="cid"/>
		<result column="cname" property="cname"/>
	</collection>
</resultMap>


<select id="selectNewsLabelById" resultMap="studentMapping">
	select sid,sname,cid,cname
	from student,middle,course
	where sid = studentId and cid = courseId and sid=#{sid}
</select>
	
</mapper>

多对多转换为一对多,采用多表连接查询方式解决。

 

<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、付费专栏及课程。

余额充值