mybatis collection 高级映射出错问题解决

本文介绍了在使用MyBatis的Collection高级映射时遇到的一对多查询结果重复和缺失的问题。作者通过分析发现,查询结果在没有明确排序时,MyBatis在封装数据时可能导致混乱。解决方案是在SQL查询语句中添加主键排序,从而解决了问题。此问题可能源于MyBatis的一个潜在bug。

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

问题: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>



补充:有前辈研究过了类似的问题:点击打开链接







评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值