2009-09-11 94 views
5

我有我相信是一個相當普遍的問題,我不想重新發明輪子。 我有一個搜索表單,用戶可以在其中指定搜索條件和搜索類型(AND OR Ext ..)。動態創建用戶的WHERE子句搜索條件

表單將ID映射到列名稱和值。目前,我使用服務器端Java將字符串粘合到一個where子句中。它在某些情況下有效,但它笨重,容易出錯,並且不能很好地擴展。

有什麼建議嗎?

感謝,

大衛

+2

你能詳細說明爲什麼你覺得這是笨重和容易出錯嗎?也許你可以發佈一些示例代碼來說明這一點。 – 2009-09-11 13:52:05

回答

0

你必須建立在客戶端或服務器上的搜索字符串。在客戶端構建它顯然不是一個好的解決方案(安全方面),所以唯一的選擇是在服務器上構建它。就個人而言,我會使用或建立一個Searcher對象,它可以有效地處理構建搜索字符串的循環任務,並從那裏創建一個Statement。

1

如果您使用的是ORM(我使用Hibernate),則可以使用Criteria API: 它允許您彙總條件(例如使用循環)並生成結果查詢。

在原生SQL中,我不知道會這樣做的庫。 也許你可以自己寫,從Hibernate Criteria的文檔和代碼中獲得靈感?


OR:

如果你做的東西在客戶端上足夠複雜(比如你管理AND和OR之間的優先級,你可以使用括號嵌套條件......),那麼你很可能已經開始建造數據結構在客戶端處理這個。

在這種情況下,我建議您將該數據結構發送到服務器,並通過循環使用它來構建查詢。

0

Hibernate有一個Criteria API,它允許僅使用方法調用創建動態查詢,而無需手動組合SQL查詢。

但是您應該考慮使用像Lucene或Hibernate Search這樣的全文搜索解決方案,這樣可以大大減少複雜條件查詢的需求。全文搜索對於用戶體驗來說也是一個更好的解決方案,因爲全文搜索更容易執行並且通常會提供更好的結果。

1

我會使用準備和?無論如何,如果只是爲了避免注入和其他misconversion風險。

如果您的搜索條件大小有限,您可以靜態列出所有可能的查詢以準備。

如果不是,您可以動態維護一個準備好的查詢池。這對於一個Web應用程序來說並不是那麼有用,在那裏你可能不會重用你準備的任何查詢。

0

Massimiliano Fliri建議看Criteria API讓我朝着正確的方向前進。我停止了關於構建「只是一個where子句」的事情,並開始考慮將此視爲構建語句的需要。

這使我一個解決方案: 的Squiggle-SQL:http://code.google.com/p/squiggle-sql/

從文檔:

Squiggle的是動態生成SQL SELECT語句一個小的Java庫。對於那些需要構建複雜查詢的應用程序來說,這是一個甜蜜點,它的運行時標準會發生變化。通常,弄清楚如何構建這個字符串會非常痛苦。 Squiggle把這種痛苦帶走了。

+0

僅供參考:初看之後,該庫似乎不支持預先準備的語句和參數。例如,字符串似乎直接嵌入到庫生成的SQL中。這可能導致SQL注入攻擊漏洞。我可能是錯的... – 2009-09-11 15:34:33

0

如果您使用Hibernate作爲ORM,那麼請使用Criteria API執行此操作。基於某些條件,添加/刪除子句會更容易。

如果你正在建設一個JDBC查詢記住這是不變的第一部分和附加的變化部分e.g

SELECT * FROM跨其中userid =?

並根據條件附加例如
如果金額!= null,則附加'和金額>? '

只要你能保持不變部分與不同部分的良好隔離,你就不應該有太多問題。

0

Adam Machanic撰寫的「專家SQL Server 2005開發」一書在第7章中有關於動態SQL的一些極好的建議。他潛入各種問題,包括性能,可維護性和安全性。我不會試圖重寫他的章節 - 可以說,當談到SQL時,他認爲更少更多。

它特定於SQL Server,但我相信他的一般方法(巨大的where子句與if/then SQL vs. dynamic)可以在整個板上應用。

編輯:我覺得值得...添加...永遠不要信任客戶端的輸入,總是在使用SQL之前參數化您的輸入。