Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql MyBatis RowBounds不限制查询结果_Sql_Spring_Oracle_Mybatis - Fatal编程技术网

Sql MyBatis RowBounds不限制查询结果

Sql MyBatis RowBounds不限制查询结果,sql,spring,oracle,mybatis,Sql,Spring,Oracle,Mybatis,我正在开发一个无状态API,需要支持分页 我使用Oracle数据库。 我使用Spring和MyBatis来访问数据库 从文档中,我了解到我可以使用RowBounds类来限制查询返回的行数 但是,似乎没有对查询进行特殊优化以支持分页 例如,如果我将RowBounds设置为偏移100,共有50条记录,我希望查询中添加以下内容: (original query with the where clause...) and ROWNUM < 150 and ROWNUM >= 100 但这里

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

我使用Oracle数据库。 我使用Spring和MyBatis来访问数据库

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

但是,似乎没有对查询进行特殊优化以支持分页

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

(original query with the where clause...)
and ROWNUM < 150
and ROWNUM >= 100
但这里什么都没有,只是我手动定义的查询

这对性能来说太糟糕了,因为我可能有几千个结果

我做错了什么

谢谢。

Mybatis将许多事情留给正在使用的SQL驱动程序,而围绕RowBounds的确切行为似乎就是其中之一

请参阅,特别是以下章节:

不同的驾驶员能够达到不同的效率水平 在这方面。为了获得最佳性能,请使用结果集类型 SCROLL\u-SENSITIVE或SCROLL\u-SENSITIVE换言之:not 只向前看

默认设置显然是未设置的,但是您可以尝试在选择标记中使用SCROLL_SENSITIVE作为ResultSetType属性,看看这是否有帮助。请参阅以了解更多信息

如果这不起作用,您可以通过放弃RowBounds的使用来解决这个问题,并实现一个SettingsBean类或类似的类,您的select标记将其作为参数类型,其中包含偏移量和限制字段,或者rowStart和rowEnd对Oracle更有意义,然后,您可以根据需要在运行时设置它们,并在执行select时将它们动态插入SQL

在编写更多代码的同时,您可以通过纯动态SQL完全按照自己的意愿控制行为。我对Mybatis和Postgres采用了类似的方法,效果很好

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

<select
  id="selectFoo"
  parameterType="com.foo.bar.SettingsBean">

select *
from foo
where rownum >= #{rowStart}
  and rownum < #{rowEnd}
</select>

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

RowBounds rowbounds = new RowBounds(0, resultLimit);
roster = tableMapper.selectAll(rowbounds);
映射器java

public List<Row> selectAll(RowBounds rowbounds);
映射器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>
我测试了Postgres数据库和AngularUI的分页。第一页是N°1,如果调用第N°0页,服务将返回所有数据

java服务:

java映射器:

xml映射器:

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

将rownum包装为嵌套查询:
谢谢RowBounds似乎永远不会使用Oracle rownum技术。此外,resultSetType设置似乎仅与有状态、基于web的应用程序相关,例如显示分页结果的网页。我将无状态EJB与Spring和MyBatis一起使用,所以我想在我的情况下,它会有什么不同?看来我得重新使用rownum解决方案了。我真的认为MyBatis团队应该更清楚地传达RowBounds的局限性。他们把它描述为一种简单抽象的分页方式,但实际上它的用途非常有限。当然,没问题。从理论上讲,即使在无状态应用程序中,它也可以工作——只需要具有不同偏移量和限制的顺序查询。然而,这实际上取决于Oracle驱动程序如何处理它,因为一次获取的行数取决于JDBC层,而JDBC层又依赖于Oracle、Postgres等各个驱动程序。。我同意这是为了让事情变得更简单。我发现Mybatis在处理更复杂类型(如字符串数组)的映射器时也是如此。
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);
}
public List<Foo> selectAll(RowBounds rowbounds);
<select id="selectAll" resultMap="Foo">
    SELECT * FROM foo;
</select>
select * 
  from (
        select a.*, ROWNUM rnum 
          from .... a
         where ...
           and ROWNUM <=  :max_rows
         order by -- important 
       )
 where rnum  >= :offset
  select *
    from (
            select a.*, ROW_NUMBER() OVER (ORDER BY id) rnum
              from ....
             -- order by is not important here
         )
   where rnum between 30 and 50;