我正在开发一个需要支持分页的无状态API。
我使用的是Oracle数据库。 我使用Spring和MyBatis进行数据库访问。
从文档中,我了解到我可以使用RowBounds类来限制查询返回的行数。
然而,似乎没有对查询进行特殊优化以支持分页。
例如,如果我将RowBounds设置为使用50条记录偏移100,我希望该查询添加以下内容:
(original query with the where clause...)
and ROWNUM < 150
and ROWNUM >= 100
但那里什么都没有,它只是我手动定义的查询。
这对于表演很糟糕,因为我可能有几千个结果。
我做错了什么?
感谢。
答案 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
,其中包含parameterType
和offset
(或者limit
和rowStart
的字段对{{1}更有意义然后,您可以根据需要在运行时设置它们,并在rowEnd
执行时将它们动态插入到SQL中。
虽然代码更多,但您可以通过纯动态SQL完全按照自己的意愿控制行为。我使用了Oracle
和select
这样的方法,但效果很好。
因此,您将使用这些字段及其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 语句:
select *
from (
select a.*, ROWNUM rnum
from .... a
where ...
and ROWNUM <= :max_rows
order by -- important
)
where rnum >= :offset
其中 :max_rows
是 offset + page size
。
select *
from (
select a.*, ROW_NUMBER() OVER (ORDER BY id) rnum
from ....
-- order by is not important here
)
where rnum between 30 and 50;