Mybatis RowBounds在resultMap内部具有集合,未返回预期结果

时间:2018-07-04 22:16:37

标签: java pagination mybatis

Mapper.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分页或收藏我是否缺少某些东西?

2 个答案:

答案 0 :(得分:1)

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

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

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

<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>

答案 1 :(得分:0)

穿刺器具有有效点数。但它似乎并没有解决问题。

问题可以通过重写sql as discussed by Kazuki Shimizu解决。 基本上你必须限制一些内部/中间表,它们最终将代表从 MyBatis 映射器返回的实际实体。

或者如果您在数据库中没有很多条目,您可以在检索所有(!)项的同时在代码中实现分页。

public List<Item> getItems(Paging paging) {
    List<Item> items = itemMapper.selectItems();
    if (paging != null) {
        items = items.stream()
                .skip((long) paging.pageIndex * paging.pageSize)
                .limit(paging.pageSize)
                .collect(Collectors.toList());
    }
    return items;
}