关于MyBatis多对多关联映射的问题咨询(续前序映射问题)
嘿,我来帮你搞定这个MyBatis关联映射的问题!从你给出的实体结构来看,核心是要处理Items和Tags之间的关联(不管是一对多还是多对多场景,我都给你覆盖到),还有ObjectA里嵌套的集合映射。下面分具体场景给你可行的配置方案:
场景1:Items与Tags是一对多关联(Tags表直接存item_id外键)
这种情况是最直接的,先写关联查询的SQL,再配置MyBatis的ResultMap来映射嵌套集合:
关联查询SQL
SELECT i.id AS item_id, i.description, t.id AS tag_id, t.item_id, t.tag FROM items i LEFT JOIN tags t ON i.id = t.item_id -- 要是需要关联查询ObjectA和Products,直接在这个基础上继续JOIN对应的表就行
MyBatis XML ResultMap配置
先给Tags定义基础的ResultMap,再在Items的ResultMap里用<collection>标签嵌套映射tags集合:
<!-- Tags的基础ResultMap --> <resultMap id="TagResultMap" type="Tags"> <!-- 必须指定主键,MyBatis靠这个区分不同的Tag实例,避免重复 --> <id property="id" column="tag_id"/> <result property="item_id" column="item_id"/> <result property="tag" column="tag"/> </resultMap> <!-- Items的ResultMap,嵌套Tags集合 --> <resultMap id="ItemResultMap" type="Items"> <id property="id" column="item_id"/> <result property="description" column="description"/> <!-- collection标签用来映射集合类型的属性,ofType指定集合元素的类型 --> <collection property="tags" ofType="Tags" resultMap="TagResultMap"/> </resultMap> <!-- 如果要映射ObjectA,直接嵌套Items和Products的ResultMap即可 --> <resultMap id="ObjectAResultMap" type="ObjectA"> <collection property="items" ofType="Items" resultMap="ItemResultMap"/> <collection property="products" ofType="Products" resultMap="ProductResultMap"/> <!-- ProductResultMap需要你根据Products实体自行定义,结构和上面类似 --> </resultMap>
场景2:Items与Tags是多对多关联(通过中间表关联)
如果是真正的多对多(一个Tag对应多个Item,一个Item对应多个Tag,中间有item_tag表存关联关系),那Tags实体里的item_id可以去掉,配置如下:
关联查询SQL
SELECT i.id AS item_id, i.description, t.id AS tag_id, t.tag FROM items i LEFT JOIN item_tag it ON i.id = it.item_id LEFT JOIN tags t ON it.tag_id = t.id
MyBatis XML ResultMap配置
和一对多的配置类似,只是TagResultMap不需要映射item_id了:
<resultMap id="TagResultMap" type="Tags"> <id property="id" column="tag_id"/> <result property="tag" column="tag"/> </resultMap> <resultMap id="ItemResultMap" type="Items"> <id property="id" column="item_id"/> <result property="description" column="description"/> <collection property="tags" ofType="Tags" resultMap="TagResultMap"/> </resultMap>
常见问题排查
- 出现重复的Items对象:检查有没有给每个ResultMap正确配置
<id>标签,MyBatis必须靠主键来判断是否是同一个对象,否则会把每一行查询结果都当成新的Item实例。 - Tags集合为空:先检查SQL的JOIN条件是否正确,要是用了
INNER JOIN,没有标签的Item会被过滤掉,换成LEFT JOIN试试。 - 想用注解代替XML:可以用
@Results和@Many实现分步查询,适合数据量较大的场景(避免JOIN带来的性能损耗),示例代码如下:
@Results(id = "ItemResult", value = { @Result(property = "id", column = "item_id", id = true), @Result(property = "description", column = "description"), @Result(property = "tags", column = "item_id", many = @Many(select = "com.yourpackage.mapper.TagMapper.getTagsByItemId")) }) @Select("SELECT id AS item_id, description FROM items") List<Items> getItems();
这里的getTagsByItemId是你在TagMapper里定义的根据item_id查询Tags的方法。
内容的提问来源于stack exchange,提问作者ReiSchneider
相关产品推荐
相关产品推荐

