首页 > 解决方案 > Mybatis RowBounds 与 resultMap 内的集合不返回预期结果

问题描述

映射器.xml

<resultMap id="resultMap" type="dBWrapper">
    <result property="id" column="id" />
    <result property="code" column="code" />
    <result property="description" column="description" />
    <collection property="orderIds" ofType="java.lang.Long" >
        <result column="orderId" />
    </collection>
</resultMap>

<select id="selectAllProducts" resultMap="resultMap" parameterType="dBWrapper">
    SELECT product.id, product.code, product.description, provider.providerName, order.orderId
    FROM Product product
    LEFT JOIN Order order on product.id = order.productId
    WHERE 1=1
    <if orderSearchId != ''> 
        and order.orderId = #{orderSearchId}
    </if>
</select>

为检索分页列表而编写的 Java 代码:

productList = productMapper.selectAllProducts(searchObj, new RowBounds((searchObj.getPage() - 1) * searchObj.getTotal(), searchObj.getTotal()));

这样对于具有 3 条记录的第 1 页,使用 RowBounds(0, 3) 调用它。对于第 2 页,它使用 RowBounds(3, 3) 调用,对于第 3 页 RowBounds(6, 3)。

mybatis日志中对上述函数的SQL查询返回如下

id      code      description      orderId
-------------------------------------------
1       101       Samolina         200
1       101       Samolina         201
2       102       Trampoline       300
2       102       Trampoline       301
2       102       Trampoline       302
2       102       Trampoline       303
3       103       Pajar            401
3       103       Pajar            402
4       104       Tramtor          500
4       104       Tramtor          501
4       104       Tramtor          502
5       105       Wadnor           600
5       105       Wadnor           601
5       105       Wadnor           602
5       105       Wadnor           603
6       106       Bramget          701
6       106       Bramget          702

但是mybatis在应用分页和收集的时候,在第一页就看到了下面的记录(没问题)。

id      code      description      orderIds
-------------------------------------------
1       101       Samolina         (200,201)
2       102       Trampoline       (300,301,302,303)
3       103       Pajar            (401,402)

因此对于第二页,记录应该从 id = 4 开始。但是,这是 mybatis 为第二页返回的内容。

id      code      description      orderIds
-------------------------------------------
2       102       Trampoline       (301,302,303)
3       103       Pajar            (401,402)
4       104       Tramtor          (500,501,502)

现在,如果您查看实际查询返回的数据库,第 4 条记录如下。这就是第二页真正开始的地方。请注意第 2 页的第一条记录中缺少 300 的 orderId。这是因为 orderId = 300 是实际查询中的第三条记录,因此不包括在内。

id      code      description      orderId
-------------------------------------------
2       102       Trampoline       301

关于 mybatis 分页或集合,我有什么遗漏吗?

标签: javapaginationmybatis

解决方案


我在您的代码中看到了一些问题:

  • 如果您使用分页,则需要添加ORDER BY到您的 SQL。当不存在时,SQL 以任何顺序返回行,并且该顺序可能/将随时间改变。我认为这是您的代码中的一个严重错误。
  • 此外,强烈建议在封闭实体的某些属性上指定 <id> 标记。否则它会变得非常缓慢。
  • 此外,使用 < where > 子句代替WHERE 1=1. and如果需要,MyBatis 会在运行时自动删除第一个。

这是您的映射器的修改版本:

<resultMap id="resultMap" type="dBWrapper">
    <id property="id" column="id" /> <!-- I used ID here -->
    <result property="code" column="code" />
    <result property="description" column="description" />
    <collection property="orderIds" ofType="java.lang.Long" >
        <result column="orderId" />
    </collection>
</resultMap>

<select id="selectAllProducts" resultMap="resultMap" parameterType="dBWrapper">
    SELECT product.id, product.code, product.description, 
      provider.providerName, order.orderId
    FROM Product product
    LEFT JOIN Order order on product.id = order.productId
    <where>
      <if test="orderSearchId != null"> 
        and order.orderId = #{orderSearchId}
      </if>
    </where>
    ORDER BY product.id, order.id
</select>

推荐阅读