2009-01-08 14 views
26

¿Alguien sabe cuál es el mejor enfoque para acceder a una vista SQL a través de Grails (o si esto es posible)? Parece que una forma obvia de hacer esto sería usar executeQuery contra la vista para seleccionar una colección de filas de la vista que no trataríamos como una lista de objetos de dominio. Sin embargo, incluso en este caso, no es obvio a qué clase de dominio ejecutar executeQuery, ya que realmente solo estamos usando esa clase de dominio para ejecutar la consulta contra una entidad completamente no relacionada (la vista).SQL/Database Views in Grails

¿Sería preferible crear una clase de dominio que representara la vista y entonces podríamos simplemente usar list() contra esa clase de dominio? Parece que habría problemas con esto, ya que Grails probablemente espera poder insertar, actualizar, eliminar y modificar el esquema de tabla de cualquier clase de dominio.

[Editar:
Seguimiento pregunta aquí: Grails Domain Class without ID field or with partially NULL composite field

Respuesta

34

Usted puede utilizar SQL sin formato en Grails que es en el caso de acceder a una vista de la forma preferible (OMI):

Por ejemplo, en su controlador:

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 
    } 

} 

y la vista parte:

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

Espero que la fuente se explique por sí misma. El Documentation can be found here

+0

¡Eso se ve genial, gracias! Preferiría usar una especie de clase de dominio "virtual", pero como dije, realmente dudo de que sea posible en una situación como esta. –

+0

Años después, todavía funciona (Grails 2.0). Niche hibernate escape hatch cuando una consulta exige sql nativo. – virtualeyes

2

Es perfectamente posible asignar una clase de dominio a una vista, simplemente trátela como una tabla normal. Creo que Grails imprimirá algunos mensajes de registro sobre no poder hacer inserciones, eliminaciones, etc., pero no arrojará ningún error a menos que intente hacer algo más que consultar con la clase de dominio.

+0

Esto parece funcionar normalmente, pero tuve algunos problemas en ciertos casos. Vea el enlace adicional que agregué a la pregunta anterior si desea darle una oportunidad. ¡Gracias! –

4

Usted puede poner esto en sus asignaciones de clase de dominio:

static mapping = { 
    cache 'read-only' 
} 

Pero no estoy seguro de si esto ayuda a entender Hibernate es una vista ... http://docs.jboss.org/hibernate/stable/core/reference/en/html_single/#performance-cache-readonly

De todos modos, se utiliza la base de datos visualiza una muchas clases de dominio de grails en nuestro proyecto actual, porque HQL es un dolor en el culo y es más simple usar SQL para unir tablas.

Sin embargo, una cosa de la que debe tener cuidado es el procesamiento por lotes Hibernate de consultas (y todo el negocio de limpieza). Si inserta algo en una tabla y luego en la misma transacción selecciona una vista que depende de esa tabla, no obtendrá las últimas filas que insertó. Esto se debe a que Hibernate en realidad no habrá insertado las filas todavía, mientras que si seleccionó la tabla en la que insertó las filas, Hibernate se habrá dado cuenta de que necesitaba eliminar las consultas pendientes antes de darle el resultado de su selección.

Una solución es (flush:true) cuando guarda una instancia de dominio que sabe que necesitará leer a través de una vista en la misma transacción.

Sin embargo, sería genial tener algún tipo de forma de decirle a Hibernate que una vista/dominio depende de las otras clases de dominio, de modo que el enjuague Hibernate funciona bien sin problemas.

+0

Muy buen punto acerca de las descargas de agua cuando se trata de vistas. –