2014-06-19 72 views
2

我正在開發需要支持分頁的無狀態API。MyBatis RowBounds不限制查詢結果

我使用的是Oracle數據庫。 我使用Spring與MyBatis進行數據庫訪問。

從文檔中,我明白我可以使用RowBounds類來限制查詢返回的行數。

但是,似乎沒有對查詢進行特殊優化以支持分頁。

例如,如果我設置RowBounds有50條記錄,以抵消100,我期望的查詢有以下補充:

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

但什麼也沒有,只是我手動定義的查詢。

這對性能來說很糟糕,因爲我可能有幾千個結果。

我在做什麼錯?

謝謝。

回答

6

Mybatis留下了很多東西,直到SQL driver正在使用,並且看起來RowBounds周圍的確切行爲就是其中之一。

http://mybatis.github.io/mybatis-3/java-api.html,特別是說的部分:

不同的驅動會在這方面實現不同程度的效率 的。爲獲得最佳性能,請使用結果集類型 SCROLL_SENSITIVE或SCROLL_INSENSITIVE(換句話說:不是 FORWARD_ONLY)。

默認顯然UNSET,但你可以嘗試在select標籤使用SCROLL_SENSITIVE作爲ResultSetType屬性,看看是否有幫助。有關詳情,請參閱http://mybatis.github.io/mybatis-3/sqlmap-xml.html

如果不工作,你總是可以解決的問題,通過開溝使用RowBounds和實施SettingsBean類(或類似),你select標籤將採取爲parameterType,並且其中包含的字段offsetlimit(或者rowStartrowEnd更有意義Oracle,然後你可以設置那些在運行時根據需要,在執行select時動態插值他們到SQL。

雖然更多的代碼,你可以完全按照你的想法來控制行爲gh純動態SQL。我已經用MybatisPostgres這樣的方法,它運行良好。

所以,你會實現你的SettingsBean類這些領域和他們的getter和setter方法,然後你select語句可能看起來像:

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

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

感謝。看來RowBounds永遠不會使用Oracle rownum技術。另外,看起來resultSetType設置僅與有狀態的基於Web的應用程序相關,如顯示分頁結果的網頁。我在Spring和MyBatis中使用無狀態的EJB,所以我認爲它會使我的情況有所不同?似乎我必須迴避使用rownum解決方案。我真的認爲MyBatis團隊應該更清楚地傳達RowBounds的侷限性。他們將其描述爲分頁的簡單抽象方式,而事實上它的使用非常有限。 – odedia

+0

當然,沒問題。理論上,即使在無狀態的應用程序中,它也可以工作 - 只需要使用具有不同'偏移量'的連續查詢以及'limit'。然而,它實際上取決於Oracle驅動程序如何處理它,因爲一次要讀取的行的數量取決於JDBC層,而JDBC層依次對各個驅動程序(「Oracle」,「 Postgres'等)。我同意它的做法比它更簡單。我發現當涉及到更復雜類型的映射器時,Mybatis也是如此,例如字符串數組。 – khampson

2

我發現了一個簡單的工作,圍繞這個問題。我遵循了建議的@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> 
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的映射:

public List<Foo> selectAll(RowBounds rowbounds); 

XML映射:

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