问题:mybatis collection高级映射(不使用子查询,避免N+1),mapper配置如下:
<resultMap id="OmsSkuPoMap" type="com.trymore.pifa.domain.po.OmsSkuPo" >
<id column="sku_id" property="skuId" jdbcType="VARCHAR" />
<result column="pid" property="pid" jdbcType="INTEGER" />
<result column="price" property="price" jdbcType="NUMERIC" />
<result column="amount" property="amount" jdbcType="INTEGER" />
<result column="sku_status" property="skuStatus" jdbcType="INTEGER" />
<result column="crt_time" property="crtTime" jdbcType="TIMESTAMP" />
<result column="upd_time" property="updTime" jdbcType="TIMESTAMP" />
<result column="img_url" property="imgUrl" jdbcType="VARCHAR" />
<result column="barcode" property="barcode" jdbcType="VARCHAR" />
<result column="spec" property="spec" jdbcType="VARCHAR" />
<collection property="skuAttributes" ofType="com.trymore.pifa.domain.po.OmsSkuAttributePo">
<id column="sa_id" property="saId" jdbcType="INTEGER" />
<result column="paid" property="paid" jdbcType="INTEGER" />
<result column="pavid" property="pavid" jdbcType="INTEGER" />
<result column="attribute_name" property="attributeName" jdbcType="VARCHAR" />
<result column="attribute_value" property="attributeValue" jdbcType="VARCHAR" />
</collection>
</resultMap>
<select id="selectSkuAndAttributeByCondition" resultMap="OmsSkuPoMap" parameterType="java.util.Map">
SELECT
skua.sa_id,
skua.paid,
skua.pavid,
pa.attribute_name attribute_name,
pav.attribute_value attribute_value,
<include refid="Base_Column_List_Alias" />
FROM pifa.sku sku
LEFT JOIN pifa.sku_attribute skua ON sku.sku_id = skua.sku_id
LEFT JOIN pifa.product_attribute pa ON skua.paid = pa.paid
LEFT JOIN pifa.product_attribute_value pav ON skua.pavid = pav.pavid
<where>
<if test="pid != null">
AND sku.pid = #{pid}
</if>
</where>
</select>
po类结构如下:
public class OmsSkuPo {
private String skuId;
private Integer pid;
private BigDecimal price;
private Integer amount;
private Integer skuStatus;
private Date crtTime;
private Date updTime;
private String imgUrl;
private String barcode;
private Integer makerId;
private String spec;
/**
* 额外字段
*/
private List<OmsSkuAttributePo> skuAttributes;
作者目的在于快速方便的使用一次查询查出sku表和sku_attributes等表的记录,他们之间的关系是一对多。于是很快想到了mybatis collection的使用,就是用了如上的配置方法。但结果是,查询出来的记录有重复的,还有缺少的。作者猜想肯定是mybatis在封装一对多时,对查询出来的多条记录进行比较的时候有问题,才会导致封装结果出现混乱。网上找了很久没有找到办法。。。
最后解决办法:作者偶然发现在sql语句中加入排序即可解决问题。估计是mybatis在处理这个问题的时候有一定的bug,按照主键排序即可。以后阅读源码看看。
<select id="selectSkuAndAttributeByCondition" resultMap="OmsSkuPoMap" parameterType="java.util.Map">
SELECT
skua.sa_id,
skua.paid,
skua.pavid,
pa.attribute_name attribute_name,
pav.attribute_value attribute_value,
<include refid="Base_Column_List_Alias" />
FROM pifa.sku sku
LEFT JOIN pifa.sku_attribute skua ON sku.sku_id = skua.sku_id
LEFT JOIN pifa.product_attribute pa ON skua.paid = pa.paid
LEFT JOIN pifa.product_attribute_value pav ON skua.pavid = pav.pavid
<where>
<if test="pid != null">
AND sku.pid = #{pid}
</if>
</where>
order by sku.sku_id,skua.paid <!-- 此处排序不可修改哟,否则mybatis collection映射会有问题 -->
</select>
补充:有前辈研究过了类似的问题:点击打开链接