2009-01-08 17 views
26

有沒有人知道通過Grails訪問sql視圖的最佳方法是什麼(或者甚至可能)?看起來這樣做的一個顯而易見的方法是對視圖使用executeQuery來從視圖​​中選擇一個行集合,我們不會將其視爲域對象列表。但是,即使在這種情況下,運行executeQuery的域類也不明顯,因爲實際上我們只是使用該域類來針對完全不相關的實體(視圖)運行查詢。Grails中的SQL /數據庫視圖

創建一個表示視圖的域類,然後我們可以使用list()對該域類進行創建嗎?看起來會有問題,因爲Grails可能希望能夠插入,更新,刪除和修改任何域類的表模式。

[編輯:
這裏後續問題:Grails Domain Class without ID field or with partially NULL composite field

回答

34

可使用普通SQL在Grails的是在訪問視圖(IMO)的最好方式的情況下:

例如,在您的控制器:

import groovy.sql.Sql 

class MyFancySqlController { 

    def dataSource // the Spring-Bean "dataSource" is auto-injected 

    def list = { 
     def db = new Sql(dataSource) // Create a new instance of groovy.sql.Sql with the DB of the Grails app 

     def result = db.rows("SELECT foo, bar FROM my_view") // Perform the query 

     [ result: result ] // return the results as model 
    } 

} 

和視圖部分:

<g:each in="${result}"> 
    <tr> 
     <td>${it.foo}</td> 
     <td>${it.bar}</td> 
    </tr> 
</g:each> 

我希望來源不言自明。 Documentation can be found here

+0

這看起來不錯,謝謝!我更喜歡使用一種「虛擬」域類,但就像我說的,我真的懷疑在這種情況下甚至可能。 – 2009-01-08 19:07:20

+0

多年後,仍然有效(Grails 2.0)。當查詢要求本地sql時,好的hibernate逃脫孵化。 – virtualeyes 2011-10-04 13:55:30

2

完全有可能將一個域類映射到一個視圖,只是把它看作一個常規的表。我認爲Grails會打印一些關於不能進行插入,刪除等的日誌消息,但它不會拋出任何錯誤,除非您實際嘗試執行除域類查詢之外的其他操作。

+0

這似乎通常工作,但在某些情況下我有一些問題。如果你想給它一個鏡頭,請參閱我添加到上面問題的附加鏈接。謝謝! – 2009-01-09 22:55:11

4

你可以把這個在你的領域類的映射:

static mapping = { 
    cache 'read-only' 
} 

但我不知道這是否有助於Hibernate的理解這是一個觀點... http://docs.jboss.org/hibernate/stable/core/reference/en/html_single/#performance-cache-readonly

不管怎樣,我們使用數據庫視圖一個在我們當前的項目中作爲grails領域類很多,因爲HQL是屁股的痛苦,使用SQL來連接表更簡單。

有一點你需要小心,但是,Hibernate的批量查詢(和整個沖洗業務)。如果您在表中插入某些內容,然後在同一個事務中選擇依賴於該表的視圖,則不會獲取插入的最新行。這是因爲Hibernate實際上並沒有插入行,而如果你選擇了插入行的表,Hibernate會在給你選擇的結果之前計算出它需要清除其掛起的查詢。

一個解決方案是(flush:true)當保存一個域實例,你知道你將需要在同一個事務中通過一個視圖讀取。

然而,有一種很酷的方式可以告訴Hibernate一個視圖/域依賴於哪些其他的域類,這樣Hibernate的刷新就可以無縫運行。