Question

Quelqu'un sait-il quelle est la meilleure approche pour accéder à une vue SQL via Grails (ou même si cela est possible)? Il semble qu'un moyen évident de le faire serait d'utiliser executeQuery avec la vue pour sélectionner une collection de lignes dans la vue que nous ne traiterions pas comme une liste d'objets de domaine. Cependant, même dans ce cas, il n’est pas évident de choisir la classe de domaine sur laquelle exécuter executeQuery, puisqu’en réalité, nous ne l’utilisons que pour exécuter la requête sur une entité totalement indépendante (la vue).

Serait-il préférable de créer une classe de domaine représentant la vue et nous pourrions alors simplement utiliser list () contre cette classe de domaine? Cela semble poser problème, car Grails s’attend probablement à pouvoir insérer, mettre à jour, supprimer et modifier le schéma de table de n’importe quelle classe de domaine.

[Edit:
Question de suivi ici: Domaine de Grails Classe sans champ ID ou avec un champ composite partiellement NULL

Était-ce utile?

La solution

Vous pouvez utiliser du SQL pur dans Grails, qui consiste à accéder à une vue de manière préférable (IMO):

Par exemple dans votre contrôleur:

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
    }

}

et la partie vue:

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

J'espère que la source se passe d'explication. La documentation est disponible ici

.

Autres conseils

Vous pouvez insérer ceci dans vos mappages de classe de domaine:

static mapping = {
    cache 'read-only'
}

Mais je ne suis pas sûr que cela aide Hibernate à comprendre que c'est une vue ... http://docs.jboss.org/hibernate/stable/core/reference/en/html_single/#performance-cache-readonly

Quoi qu'il en soit, nous utilisons beaucoup les vues de base de données en tant que classes de domaine Grails dans notre projet actuel, car HQL est un jeu d'enfant et il est plus simple d'utiliser SQL pour joindre des tables.

Une chose à laquelle vous devez cependant faire attention est le traitement par lots de requêtes Hibernate (et l’ensemble du flush). Si vous insérez quelque chose dans une table, puis sélectionnez dans la même transaction une vue qui dépend de cette table, vous n'obtiendrez pas les dernières lignes que vous avez insérées. En effet, Hibernate n’aura pas encore inséré les lignes, alors que si vous avez sélectionné le tableau dans lequel vous avez inséré des lignes, Hibernate aurait compris qu’il devait vider ses requêtes en attente avant de vous donner le résultat de votre sélection.

Une solution consiste à ( flush: true ) lors de la sauvegarde d'une instance de domaine dont vous savez qu'il vous faudra lire une vue par la suite dans la même transaction.

Ce serait bien d’avoir un moyen de dire à Hibernate qu’un point de vue / domaine dépend de quelles autres classes de domaine, de sorte que le vidage Hibernate fonctionne sans problème.

Il est parfaitement possible de mapper une classe de domaine sur une vue, il suffit de la traiter comme une table normale. Je pense que Grails imprimera quelques messages de journalisation indiquant qu'il est impossible de faire des insertions, des suppressions, etc., mais il ne générera aucune erreur à moins que vous n'essayiez réellement de faire autre chose qu'une requête avec la classe de domaine.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top