web-dev-qa-db-ja.com

GrailsのSQL /データベースビュー

Grailsを介してSQLビューにアクセスするための最良のアプローチは何か知っていますか(またはこれが可能かどうか)?これを行う明らかな方法は、ビューに対してexecuteQueryを使用して、ドメインオブジェクトのリストとして扱わないビューから行のコレクションを選択することです。ただし、この場合でも、executeQueryを実行するドメインクラスは明確ではありません。実際には、完全に無関係なエンティティ(ビュー)に対してクエリを実行するためにそのドメインクラスを使用しているだけだからです。

ビューを表すドメインクラスを作成して、そのドメインクラスに対してlist()を使用することをお勧めしますか? Grailsはおそらく、任意のドメインクラスのテーブルスキーマを挿入、更新、削除、および変更できることを期待しているため、これには問題があるようです。

[編集:
ここで質問をフォローアップしてください: IDフィールドのないまたは部分的にNULLの複合フィールドを持つGrailsドメインクラス

26
Chris King

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>

ソースが自明であることを願っています。 ドキュメントはここにあります

34

これをドメインクラスマッピングに入れることができます:

static mapping = {
    cache 'read-only'
}

しかし、それがHibernateがビューであることを理解するのに役立つかどうかはわかりません... http://docs.jboss.org/hibernate/stable/core/reference/en/html_single/#performance-cache-readonly

とにかく、現在のプロジェクトではデータベースビューをgrailsドメインクラスとしてよく使用します。これは、HQLがお尻の痛みであり、SQLを使用してテーブルを結合する方が簡単だからです。

ただし、注意が必要なことの1つは、クエリのHibernateバッチ処理(およびフラッシュビジネス全体)です。テーブルに何かを挿入した後、同じトランザクションでそのテーブルに依存するビューを選択した場合、挿入した最新の行は取得されません。これは、Hibernateが実際にはまだ行を挿入していないのに対し、行を挿入したテーブルを選択した場合、Hibernateは、選択の結果を表示する前に、保留中のクエリをフラッシュする必要があると判断したためです。

1つの解決策は(flush:true)ドメインインスタンスを保存するときは、同じトランザクションで後でビューを読み取る必要があることがわかっています。

ただし、ビュー/ドメインが他のどのドメインクラスに依存するかをHibernateに伝える何らかの方法があると便利です。そのため、Hibernateのフラッシュは見た目が悪くなります。

4
Felix GV

ドメインクラスをビューにマップすることは完全に可能であり、通常のテーブルのように扱うだけです。 Grailsは、挿入や削除などを実行できないことに関するログメッセージを出力すると思いますが、ドメインクラスでクエリ以外のことを実際に実行しようとしない限り、エラーはスローされません。

2
Ben Williams