MyBatis RowBounds不限制查询结果

时间:2014-06-19 08:15:27

标签: sql spring oracle mybatis

我正在开发一个需要支持分页的无状态API。

我使用的是Oracle数据库。 我使用Spring和MyBatis进行数据库访问。

从文档中,我了解到我可以使用RowBounds类来限制查询返回的行数。

然而,似乎没有对查询进行特殊优化以支持分页。

例如,如果我将RowBounds设置为使用50条记录偏移100,我希望该查询添加以下内容:

(original query with the where clause...)
and ROWNUM < 150
and ROWNUM >= 100

但那里什么都没有,它只是我手动定义的查询。

这对于表演很糟糕,因为我可能有几千个结果。

我做错了什么?

感谢。

4 个答案:

答案 0 :(得分:8)

Mybatis将许多内容留给正在使用的SQL driver,看来围绕RowBounds的确切行为就是其中之一。

请参阅http://mybatis.github.io/mybatis-3/java-api.html,特别是以下部分:

  

不同的驱动程序能够达到不同的效率水平   在这方面。为获得最佳性能,请使用结果集类型   SCROLL_SENSITIVE或SCROLL_INSENSITIVE(换句话说:不是   FORWARD_ONLY)。

默认显然是UNSET,但您可以尝试将SCROLL_SENSITIVE用作ResultSetType标记中的select属性,看看是否有帮助。有关详细信息,请参阅http://mybatis.github.io/mybatis-3/sqlmap-xml.html

如果这不起作用,您可以通过放弃使用RowBounds并实施设置广告类(或类似)来解决问题。 }标记将作为select,其中包含parameterTypeoffset(或者limitrowStart的字段对{{1}更有意义然后,您可以根据需要在运行时设置它们,并在rowEnd执行时将它们动态插入到SQL中。

虽然代码更多,但您可以通过纯动态SQL完全按照自己的意愿控制行为。我使用了Oracleselect这样的方法,但效果很好。

因此,您将使用这些字段及其getter和setter实现 SettingsBean 类,然后您的Mybatis语句可能如下所示:

Postgres

答案 1 :(得分:4)

我找到了一个简单的解决这个问题的方法。我遵循了@khampson推荐的Mybatis指令,并将RowBounds实例传递给mapper,没有强制执行限制。

RowBounds rowbounds = new RowBounds(0, resultLimit);
roster = tableMapper.selectAll(rowbounds);

mapper java

public List<Row> selectAll(RowBounds rowbounds);

mapper xml

<select id="com.TableMapper.selectAll" resultMap="row" timeout="10">
            SELECT * FROM table;
</select>

只需将“LIMIT#{param1.offset},#{param1.limit}”附加到映射器的xml就会产生我想要的行为!

<select id="com.TableMapper.selectAll" resultMap="row" timeout="10"> 
    SELECT * FROM table LIMIT #{param1.offset}, #{param1.limit}; 
</select>

答案 2 :(得分:0)

我测试了 Postgres数据库以及AngularUI的分页。第一页为N°1,如果您调用第N°0页,则服务将返回所有数据。

java服务:

public List<Foo> selectAll(int currentPage, int itemsPerPage);
    int offset = (currentPage - 1) * itemsPerPage;
    RowBounds rowbounds;
    if(currentPage == 0){
        rowBounds = new RowBounds();
    } else {
        rowBounds = new RowBounds(currentPage, itemsPerPage);
    }
    return fooMapper.selectAll(rowBounds);
}

java Mapper:

public List<Foo> selectAll(RowBounds rowbounds);

xml Mapper:

<select id="selectAll" resultMap="Foo">
    SELECT * FROM foo;
</select>

答案 3 :(得分:0)

Rownum 是 Oracle 中的伪列,意味着它在最后阶段添加到结果集中。这意味着,将 rownum 与大于 1 的任何值进行比较总是不返回任何记录。有 2 个选项可以修改您的 SQL 语句:

  1. 将 rownum 包装为嵌套查询:
select * 
  from (
        select a.*, ROWNUM rnum 
          from .... a
         where ...
           and ROWNUM <=  :max_rows
         order by -- important 
       )
 where rnum  >= :offset

其中 :max_rowsoffset + page size

  1. 使用分析函数:
  select *
    from (
            select a.*, ROW_NUMBER() OVER (ORDER BY id) rnum
              from ....
             -- order by is not important here
         )
   where rnum between 30 and 50;