MyBatis Generator XML配置多表关联,能否生成关联类与方法?
当然可以!MyBatis 完全支持通过 XML 配置来实现这种多层关联的映射,还能帮你定义带关联逻辑的查询方法(不过实体类通常需要你先定义好,或者用 MyBatis Generator 生成基础实体后再补充关联字段)。下面一步步给你讲具体怎么配置:
第一步:定义关联实体类
首先得把三个表对应的实体类准备好,要包含关联关系的字段:
One类:包含主键id,以及一个List<Two>类型的twos(一个 One 对应多个 Two)Two类:包含主键id、field,以及One类型的one(关联父表 One)、List<Three>类型的threes(关联符合条件的 Three)Three类:包含主键id、field,以及Two类型的two(关联父表 Two)
第二步:配置 XML 映射文件
你有两种常用的方式来实现这种关联查询:联合查询(一次性查三张表)或者嵌套查询(分步加载)。
方式一:联合查询(一次性关联三张表)
直接写一个联合 SQL,通过 LEFT JOIN 关联三张表,同时加上 TWO.FIELD = THREE.FIELD 的条件,然后用 resultMap 映射多层关联关系。
比如在 OneMapper.xml 中:
<!-- 定义结果映射,处理多层关联 --> <resultMap id="OneWithTwoAndThreeResultMap" type="com.yourpackage.One"> <!-- 映射 One 表字段 --> <id column="one_id" property="id" /> <!-- 映射关联的 Two 集合 --> <collection property="twos" ofType="com.yourpackage.Two"> <id column="two_id" property="id" /> <result column="two_field" property="field" /> <!-- 映射关联的 Three 集合,限定 TWO.FIELD = THREE.FIELD --> <collection property="threes" ofType="com.yourpackage.Three"> <id column="three_id" property="id" /> <result column="three_field" property="field" /> </collection> </collection> </resultMap> <!-- 定义查询方法 --> <select id="selectOneWithTwoAndThree" resultMap="OneWithTwoAndThreeResultMap"> SELECT o.id AS one_id, t.id AS two_id, t.field AS two_field, th.id AS three_id, th.field AS three_field FROM ONE o LEFT JOIN TWO t ON o.id = t.id LEFT JOIN THREE th ON t.id = th.two_id AND t.field = th.field WHERE o.id = #{id} </select>
方式二:嵌套查询(分步加载)
如果担心联合查询的数据量太大,可以用分步查询:先查 One 和 Two,再根据 Two 的 ID 和 Field 去查符合条件的 Three。
- 先在
ThreeMapper.xml中定义查询符合条件的 Three 的方法:
<select id="selectThreesByTwoIdAndField" resultType="com.yourpackage.Three"> SELECT id, field FROM THREE WHERE two_id = #{twoId} AND field = #{field} </select>
- 然后在
OneMapper.xml中配置关联映射:
<resultMap id="OneWithTwoAndThreeResultMap" type="com.yourpackage.One"> <id column="one_id" property="id" /> <collection property="twos" ofType="com.yourpackage.Two"> <id column="two_id" property="id" /> <result column="two_field" property="field" /> <!-- 通过 select 属性调用 ThreeMapper 的方法,传递 Two 的 ID 和 Field --> <collection property="threes" ofType="com.yourpackage.Three" select="com.yourpackage.ThreeMapper.selectThreesByTwoIdAndField" column="{twoId=two_id, field=two_field}" /> </collection> </resultMap> <select id="selectOneWithTwoAndThree" resultMap="OneWithTwoAndThreeResultMap"> SELECT o.id AS one_id, t.id AS two_id, t.field AS two_field FROM ONE o LEFT JOIN TWO t ON o.id = t.id WHERE o.id = #{id} </select>
第三步:添加 Mapper 接口方法
在对应的 Mapper 接口中添加查询方法,比如 OneMapper:
package com.yourpackage; import org.apache.ibatis.annotations.Param; import com.yourpackage.One; public interface OneMapper { One selectOneWithTwoAndThree(@Param("id") Integer id); }
一些注意点
- 记得开启 MyBatis 的驼峰命名自动映射(在 MyBatis 全局配置中设置
mapUnderscoreToCamelCase=true),这样数据库的下划线字段可以自动映射到实体类的驼峰属性 - 如果用嵌套查询,要注意 N+1 查询问题,可以通过
fetchType="eager"设置立即加载,或者配置全局懒加载策略来优化 - MyBatis Generator 可以帮你生成基础的实体类和 Mapper 代码,但关联逻辑需要你手动补充上面的
resultMap和查询方法
内容的提问来源于stack exchange,提问作者michele
相关产品推荐
相关产品推荐

