myBatis 多对多关系
myBatis Many To Many Relationship
关于我之前关于 MyBatis 中映射的问题,我现在在处理多对多关系时遇到了问题
我有以下对象
// 由于隐私问题,我无法 post 实际对象定义和 XML
class ObjectA {
List<Items> items;
List<Products> products;
//getters setters
}
class Items {
int id;
String description;
List<Tags> tags;
}
class Tags {
int id;
int item_id;
String tag;
}
SQL 涉及加入带有标签 table 的项目 table Tags.ITEM_ID = Items.ID
基本上,它 returns 行并将它们映射到这个 myBatis
<resultMap id="getObjectA" type="ObjectA">
<collection property="items" javaType="ArrayList" ofType="Items" resultMap="getItems"/>
...
</resultMap>
<resultMap="getItems" type="Items">
<id property="id" column="ITEMS.id"/>
<result property="description" column="ITEMS.description"/>
<collection property="tags" javaType="ArrayList" ofType="Tags" resultMap="getTags"/>
</resultMap>
<resultMap id="getTags" type="Tags">
<id property="id" column="TAGS.id"/>
<result property="item_id" column="TAGS.item_id"/>
<result property="tag" column="TAGS.tag"/>
</resultMap>
从技术上讲,该设置有效并且 returns 一个包含项目列表的 ObjectA,每个项目都包含标签列表。当每个项目只有一个标签时,映射很好,但是当一个项目包含多个标签时,它会创建多个具有相同 ID 的项目,每个项目包含一个列表,该列表仅包含查询结果中的一个标签。
为父对象创建了重复的事实意味着mybatis无法正确识别对象,即<id property="id" column="ITEMS.id"/>
没有按预期工作。基本上需要id
元素,这样mybatis就知道结果集中多行重复的父记录指的是同一个对象。
一个可行的选择是确保来自不同 table 的列具有唯一名称并在结果映射中使用该唯一名称。
对于您来说,示例映射器应如下所示:
<resultMap type="ObjectA" id="objectaMap">
<id column="id" property="id"/>
<collection property="items" javaType="ArrayList" ofType="Items" columnPrefix="ITEM_">
<id column="id" property="id"/>
<result property="description" column="description"/>
<collection property="tags" javaType="ArrayList" ofType="Tags" columnPrefix="TAG_">
<id column="id" property="id"/>
<result property="tag" column="tag"/>
</collection>
</collection>
</resultMap>
<select id="getObjects" resultMap="objectaMap">
select o.*, i.id as ITEM_ID, i.description as ITEM_DESCRIPTION, t.id as ITEM_TAG_ID, t.tag as ITEM_TAG_TAG
from objecta o
join items i on (i.object_id = o.id)
join tags t on (t.item_id = i.id)
</select>
请注意 items
table 中的所有列如何具有 ITEM_
前缀以及 tags
table.
中的相同
关于我之前关于 MyBatis 中映射的问题,我现在在处理多对多关系时遇到了问题
我有以下对象
// 由于隐私问题,我无法 post 实际对象定义和 XML
class ObjectA {
List<Items> items;
List<Products> products;
//getters setters
}
class Items {
int id;
String description;
List<Tags> tags;
}
class Tags {
int id;
int item_id;
String tag;
}
SQL 涉及加入带有标签 table 的项目 table Tags.ITEM_ID = Items.ID
基本上,它 returns 行并将它们映射到这个 myBatis
<resultMap id="getObjectA" type="ObjectA">
<collection property="items" javaType="ArrayList" ofType="Items" resultMap="getItems"/>
...
</resultMap>
<resultMap="getItems" type="Items">
<id property="id" column="ITEMS.id"/>
<result property="description" column="ITEMS.description"/>
<collection property="tags" javaType="ArrayList" ofType="Tags" resultMap="getTags"/>
</resultMap>
<resultMap id="getTags" type="Tags">
<id property="id" column="TAGS.id"/>
<result property="item_id" column="TAGS.item_id"/>
<result property="tag" column="TAGS.tag"/>
</resultMap>
从技术上讲,该设置有效并且 returns 一个包含项目列表的 ObjectA,每个项目都包含标签列表。当每个项目只有一个标签时,映射很好,但是当一个项目包含多个标签时,它会创建多个具有相同 ID 的项目,每个项目包含一个列表,该列表仅包含查询结果中的一个标签。
为父对象创建了重复的事实意味着mybatis无法正确识别对象,即<id property="id" column="ITEMS.id"/>
没有按预期工作。基本上需要id
元素,这样mybatis就知道结果集中多行重复的父记录指的是同一个对象。
一个可行的选择是确保来自不同 table 的列具有唯一名称并在结果映射中使用该唯一名称。
对于您来说,示例映射器应如下所示:
<resultMap type="ObjectA" id="objectaMap">
<id column="id" property="id"/>
<collection property="items" javaType="ArrayList" ofType="Items" columnPrefix="ITEM_">
<id column="id" property="id"/>
<result property="description" column="description"/>
<collection property="tags" javaType="ArrayList" ofType="Tags" columnPrefix="TAG_">
<id column="id" property="id"/>
<result property="tag" column="tag"/>
</collection>
</collection>
</resultMap>
<select id="getObjects" resultMap="objectaMap">
select o.*, i.id as ITEM_ID, i.description as ITEM_DESCRIPTION, t.id as ITEM_TAG_ID, t.tag as ITEM_TAG_TAG
from objecta o
join items i on (i.object_id = o.id)
join tags t on (t.item_id = i.id)
</select>
请注意 items
table 中的所有列如何具有 ITEM_
前缀以及 tags
table.