2011-05-21 101 views
5

作爲工作流引擎的一部分,我正在實現一個通用的數據庫步驟,該步驟將執行任何給定的SQL查詢並將結果作爲XML返回。該工作流程可以動態配置,因此傳遞給執行層的查詢將是一個完全限定的靜態SQL查詢,例如尋找從Java中給定的SQL查詢創建動態SQL的方法

SELECT * FROM USER WHERE USERID = 10
。這種方法的缺點是數據庫每次運行時都會編譯查詢。有沒有辦法我可以通過編程方式從查詢中創建動態SQL查詢。像JPA這樣的Java或Hibernate是否支持這種功能?

+0

這個問題的最佳答案可能是你在找什麼:http://stackoverflow.com/questions/222019/how-to-use-mysql-prepared-statement-caching – 2011-05-21 03:51:31

回答

0

一般而言,您需要使用綁定變量將您的輸入參數化爲查詢模板。有兩種形式的綁定變量,即i)未命名的綁定變量(或位置綁定變量);和ii)命名綁定變量。

這可以通過vanilla JDBC完成。我發現Spring JDBC特別容易操作。特別看看JDBCTemplate接口和它的實現

+0

我可以參數化查詢,如果我知道查詢模板編譯時間。在我的情況下,我只會得到一個完整的查詢與所有變量設置。我如何從填充的查詢中提取模板?爲了進行比喻,我想爲數據庫寫一個GUI,用戶可以執行任意的隨機查詢,但大部分時間查詢都會重複進行,從而留下優化的機會。 – Kannan 2011-05-21 09:36:36

+0

要求是,當我得到一個輸入查詢「SELECT * FROM用戶,其中,USER_ID = 10」我應該能夠產生一份書面聲明「SELECT * FROM用戶,其中,USER_ID =?」並確定我需要將參數在第一個位置設置爲10的整型。 – Kannan 2011-05-21 15:14:09

+0

如果只是你提到的一種情況,那麼去字符串解析。如果你想它通用於所有查詢你需要用自己的SQL語法實現分析器 – kuriouscoder 2011-05-21 15:28:54

1

我同意用戶kuriouscoder,你應該使用綁定變量。這適用於普通的JDBC。大多數RDBMS都有一個遊標緩存,如果查詢是相同的(即沒有內聯變量),則遊標緩存保留查詢的解析版本以及內存中的執行計劃。所以解析器的開銷會很小。

就XML輸出而言,我可以推薦jOOQ(我是開發者)。在即將發佈的1.6.2版本中,我將爲各種格式(XML,HTML,JSON,CSV)添加導出功能。您的查詢將與jOOQ的流暢API來構建,它應該是這樣的:

String xml = create.selectFrom(USER) 
        .where(USERID.equal(10)) 
        .fetch() 
        .formatXML(); 

輸出看起來就像這樣(並且可以XSL轉換爲任何其他格式):

<result> 
    <fields> 
    <field name="USERID"/> 
    <field name="FIRSTNAME"/> 
    <field name="LASTNAME"/> 
    ... 
    </fields> 
    <records> 
    <record> 
     <value field="USERID">1</value> 
     <value field="FIRSTNAME">Lukas</value> 
     <value field="LASTNAME">Eder</value> 
     ... 
    </record> 
    ... 
    </records> 
</result> 

更多詳細信息,請參閱http://www.jooq.org

0

如果我明白你在問什麼,那麼你應該查看empiredb http://incubator.apache.org/empire-db/ - 這是一個相當小的項目,但至少在我使用它時,得到了積極和有力的支持。它就像python的sqlalchemy一樣,它可以讓你使用語言中的類和函數構造sql查詢。

從鏈接引用:

類型安全,串自由和直觀的API。構建包含select子句的任何SQL語句,並將其用於任何POJO而不僅僅是全功能實體bean。

1

我在項目中使用了MyBatis以獲得非常類似的行爲。 另請參閱User Guide以獲取完整信息。

在MyBatis中,您可以使用動態SQL定義查詢;你可以向SqlMapClient傳遞一個包含屬性的對象(例如POJO或Map),並在查詢文本中將它們用作:

  • #parameters#(就像?在預處理語句)
  • $變量$直接成爲SQL字符串的部分
  • 動態SQL功能,包括基於性能的SQL的部分值

那麼你的SQL映射器將執行查詢並返回一個Java對象:如果從查詢返回的記錄已知,則可以將列映射到POJO;否則在MyBatis中,可以將HashMap作爲結果類,最終通過SqlMapClient的queryWithRowHandler()方法處理每個記錄,以處理返回的數據。

一旦你至少有查詢的一個HashMap表示你就可以輕鬆地將它的XML。