GrailsのSQL /データベースビュー
質問
Grailsを介してsqlビューにアクセスするための最良のアプローチを知っている人はいますか(またはこれが可能な場合でも)。これを行う明らかな方法は、ビューに対してexecuteQueryを使用して、ドメインオブジェクトのリストとして扱わないビューから行のコレクションを選択することです。ただし、この場合でも、どのドメインクラスに対してexecuteQueryを実行するかは明確ではありません。実際には、まったく関係のないエンティティ(ビュー)に対してクエリを実行するためにそのドメインクラスを使用しているだけです。
ビューを表すドメインクラスを作成し、そのドメインクラスに対してlist()を使用することができますか? Grailsはおそらく、任意のドメインクラスのテーブルスキーマを挿入、更新、削除、および変更できると予想しているため、これには問題があるようです。
[編集:
ここで質問をフォローアップしてください: GrailsドメインIDフィールドがない、または部分的にNULLの複合フィールドを持つクラス
解決
GrailsでプレーンSQLを使用できます。これは、ビューに望ましい方法(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>
ソースが自明であることを願っています。 ドキュメントはここにあります
他のヒント
これをドメインクラスマッピングに含めることができます:
static mapping = {
cache 'read-only'
}
しかし、Hibernateがビューであることを理解するのに役立つかどうかはわかりません... http://docs.jboss.org/hibernate/stable/core/reference/en/html_single/#performance-cache-readonly
とにかく、現在のプロジェクトではHQLが苦痛であり、SQLを使用してテーブルを結合する方が簡単であるため、現在のプロジェクトではデータベースビューをgrailsドメインクラスとして多く使用しています。
ただし、注意が必要なことの1つは、クエリのHibernateバッチ処理(およびフラッシュビジネス全体)です。テーブルに何かを挿入し、同じトランザクションでそのテーブルに依存するビューを選択した場合、挿入した最新の行は取得されません。これは、Hibernateが実際に行を挿入していないためです。一方、行を挿入したテーブルを選択した場合、Hibernateは選択の結果を表示する前に保留クエリをフラッシュする必要があると判断します。
1つの解決策は、ドメインインスタンスを保存するときに( flush:true
)、同じトランザクションでその後ビューを読み取る必要があることがわかっていることです。
ただし、ビュー/ドメインが他のどのドメインクラスに依存するかをHibernateに通知する何らかの方法があれば、Hibernateのフラッシュはうまく機能します。
ドメインクラスをビューにマップすることは完全に可能です。通常のテーブルのように扱うだけです。 Grailsは挿入、削除などができないというログメッセージを出力すると思いますが、実際にドメインクラスでクエリ以外のことをしようとしない限り、エラーはスローされません。