2009-11-02 136 views
12

我的Java(JDK6)項目對其所有數據庫訪問使用SpringJDBCTemplate。我們最近從Spring 2.5升級到Spring 3(RC1)。該項目不使用像HibernateEJB這樣的ORM。Java編程 - Spring和JDBC模板 - 使用查詢,queryForList或queryForRowSet?

如果我需要閱讀了一系列的記錄,並與他們做一些內部處理,好像有幾個(重載)方法:查詢的queryForList和queryForRowSet

什麼應該是使用的標準之一而不是其他?是否有任何性能差異?最佳實踐?

您能否推薦一些外部參考資料用於進一步研究此主題?

回答

34

我發現標準的訪問方式是通過query()方法而不是任何其他方法。 query和其他方法之間的主要區別是您必須實現其中一個回調接口(RowMapperRowCallbackHandlerResultSetExtractor)來處理您的結果集。

A RowMapper很可能是您在大部分時間使用的。它在結果集的每一行對應於列表中的一個對象時使用。你只需要實現一個方法mapRow,在那裏填充你的行中的對象類型並返回它。 Spring還有一個BeanPropertyRowMapper,它可以通過將bean屬性名稱與列名稱進行匹配來填充列表中的對象(注意這個類是爲了方便而不是性能)。

A RowCallbackHandler當你需要你的結果不僅僅是一個簡單的列表時更有用。你必須自己管理返回對象,你正在使用這種方法。當我需要一個地圖結構作爲我的返回類型時(即用於樹表的分組數據,或者如果我正在創建基於主鍵的自定義緩存),我通常會發現自己正在使用它。

當您想要控制結果的迭代時,使用ResultSetExtractor。你暗示一個方法extractData將是query調用的返回值。如果我必須構建一些使用其他回調接口構建的更復雜的自定義數據結構,我纔會發現自己使用這種方法。

queryForList()方法很有價值,因爲您不必實現這些回調方法。有兩種使用queryForList的方法。首先,如果僅查詢數據庫中的單個列(例如字符串列表),則可以使用將Class作爲參數的方法版本自動爲您提供這些類的唯一對象列表。

當調用queryForList()的其他實現時,您會得到一個列表,每個條目都是每列的映射。雖然這樣做很好,因爲您可以節省編寫回調方法的開銷,但處理這種數據結構相當笨拙。由於地圖的值爲Object,因此您會發現自己正在進行大量的投射。

我從來沒有見過野外使用的queryForRowSet方法。這會將整個查詢結果加載到由Spring SqlRowSet彈出的CachedRowSet對象中。如果您將SqlRowSet傳遞給應用程序的其他層,我將看到使用此對象的一個​​大缺點,那就是將這些層耦合到您的數據訪問實現。

除了我提到的BeanPropertyRowMapper之外,您不應該在這些調用之間看到任何巨大的性能差異。如果您正在處理大型結果集的一些複雜操作,則可以通過針對您的特定案例編寫優化的ResultSetExtractor來獲得性能上的提升。

如果你想了解更多,我會諮詢Spring JDBC documentationJavaDoc for the classes I've mentioned。你也可以看看Spring框架上的一些書籍。雖然有點過時了Java Development with the Spring Framework在使用JDBC框架方面有很好的一面。最重要的是,我會說只是嘗試用每種方法編寫一些代碼,看看最適合您的是什麼。

3

既然你在美妙的泛型的土地,你可能真的想要做的是使用SimpleJdbcTemplate並使用其query()方法的對象ListsqueryForObject()爲單個對象。推理這只是因爲他們比JdbcTemplate更容易使用。

+1

AFIK兼容Java 5的查詢方法在JDBCTemplate中也可用於Spring 3 – Adrian 2009-11-02 12:34:20

+1

現在我檢查了JdbcTemplate在Spring 2.5.6中沒有使用泛型,而是在3.0.0中。我聞到了將來的棄用... :) – Esko 2009-11-02 16:10:58

+0

SimpleJdbcTemplate現在確實被棄用 – Helenesh 2017-03-21 12:05:18

2

對上述優秀答案的一個小補充:如果您正在運行一個簡單的查詢並期待一行,其他方法(如queryForInt,queryForLong,queryForMap,queryForObject等)可能看起來像是不錯的選擇。

但是,如果您可以返回0或1行,queryForList方法通常更容易,否則您必須捕獲IncorrectResultSizeDataAccessException。我瞭解到這一點很難。