3.3 El orígen de datos - Reference Documentation
Authors: Graeme Rocher, Peter Ledbrook, Marc Palmer, Jeff Brown, Luke Daley, Burt Beckwith
Version: null
Table of Contents
3.3 El orígen de datos
Since Grails is built on Java technology setting up a data source requires some knowledge of JDBC (the technology that doesn't stand for Java Database Connectivity).If you use a database other than H2 you need a JDBC driver. For example for MySQL you would need Connector/JDrivers typically come in the form of a JAR archive. It's best to use Ivy to resolve the jar if it's available in a Maven repository, for example you could add a dependency for the MySQL driver like this:
Dado que Grails se basa en la tecnología Java configurar un origen de datos requiere algunos conocimientos de JDBC (la tecnología que no es Java Database Connectivity).Si utiliza una base de datos que no sea H2 necesita un driver JDBC. Por ejemplo para MySQL sería necesario Connector/JLos drivers suelen empaquetarse en forma de un archivo JAR. Es mejor utilizar Ivy para resolver el jar si está disponible en un repositorio de Maven, por ejemplo podría añadir una dependencia para el controlador de MySQL como esta:grails.project.dependency.resolution = {
inherits("global")
log "warn"
repositories {
grailsPlugins()
grailsHome()
grailsCentral()
mavenCentral()
}
dependencies {
runtime 'mysql:mysql-connector-java:5.1.16'
}
}
Note that the built-in
Tenga en cuenta que el repositorio incorporado mavenCentral() repository is included here since that's a reliable location for this library.If you can't use Ivy then just put the JAR in your project's lib directory.Once you have the JAR resolved you need to get familiar Grails' DataSource descriptor file located at grails-app/conf/DataSource.groovy. This file contains the dataSource definition which includes the following settings:mavenCentral() se incluye aquí ya es un lugar confiable para esta biblioteca.Si no puede utilizar Ivy, ponga el jar en el directorio lib del proyecto.Una vez que tenga el jar resuelto necesita familiarizarse con el descriptor del origen de datos de Grails, ubicado en grails-app/conf/DataSource.groovy. Este archivo contiene la definición de origen de datos que incluye las siguientes opciones:driverClassName- The class name of the JDBC driverusername- The username used to establish a JDBC connectionpassword- The password used to establish a JDBC connectionurl- The JDBC URL of the databasedbCreate- Whether to auto-generate the database from the domain model - one of 'create-drop', 'create', 'update' or 'validate'pooled- Whether to use a pool of connections (defaults to true)logSql- Enable SQL logging to stdoutformatSql- Format logged SQLdialect- A String or Class that represents the Hibernate dialect used to communicate with the database. See the org.hibernate.dialect package for available dialects.readOnly- Iftruemakes the DataSource read-only, which results in the connection pool callingsetReadOnly(true)on eachConnectionproperties- Extra properties to set on the DataSource bean. See the Commons DBCP BasicDataSource documentation.
driverClassName- el nombre de clase del controlador JDBC.username- el nombre de usuario utilizado para establecer una conexión JDBC.password- la contraseña utilizada para establecer una conexión JDBC.url- la URL JDBC de la base de datos.dbCreate- si se va a generar automáticamente la base de datos del dominio modelo - uno de 'create-drop'(borrar-crear), 'create'(crear), 'update'(actualizar) o 'validate' (valiadar).pooled- si va a utilizar un pool de conexiones (de forma predeterminada es true)logSql- habilitar el registro de SQL a stdout.formatSql- formato del SQL.dialect- clase o una cadena representa el dialecto de hibertnate utilizado para comunicarse con la base de datos. Ver el paquete org.hibernate.dialect para dialectos disponibles.readOnly- sitruehace el origen de datos de sólo lectura, lo que resulta en que el pool de conexiones llama asetReadOnly(true)con cadaconexión.properties- propiedades adicionales para establecer en el bean DataSource. Consulte la documentación de Commons DBCP BasicDataSource.
dataSource {
pooled = true
dbCreate = "update"
url = "jdbc:mysql://localhost/yourDB"
driverClassName = "com.mysql.jdbc.Driver"
dialect = org.hibernate.dialect.MySQL5InnoDBDialect
username = "yourUser"
password = "yourPassword"
}When configuring the DataSource do not include the type or the def keyword before any of the configuration settings as Groovy will treat these as local variable definitions and they will not be processed. For example the following is invalid:
Cuando configurando el origen de datos se incluyen el tipo o la palabra clave de def antes de cualquiera de las opciones de configuración, Groovy tratará estas como definiciones de variables locales y no se procesarán. Por ejemplo, lo siguiente es inválido:
dataSource {
boolean pooled = true // type declaration results in ignored local variable
…
}
Example of advanced configuration using extra properties:
Ejemplo de configuración avanzada utilizando propiedades adicionales:
dataSource {
pooled = true
dbCreate = "update"
url = "jdbc:mysql://localhost/yourDB"
driverClassName = "com.mysql.jdbc.Driver"
dialect = org.hibernate.dialect.MySQL5InnoDBDialect
username = "yourUser"
password = "yourPassword"
properties {
maxActive = 50
maxIdle = 25
minIdle = 5
initialSize = 5
minEvictableIdleTimeMillis = 60000
timeBetweenEvictionRunsMillis = 60000
maxWait = 10000
validationQuery = "/* ping */"
}
}More on dbCreate
Hibernate can automatically create the database tables required for your domain model. You have some control over when and how it does this through thedbCreate property, which can take these values:
- create - Drops the existing schemaCreates the schema on startup, dropping existing tables, indexes, etc. first.
- create-drop - Same as create, but also drops the tables when the application shuts down cleanly.
- update - Creates missing tables and indexes, and updates the current schema without dropping any tables or data. Note that this can't properly handle many schema changes like column renames (you're left with the old column containing the existing data).
- validate - Makes no changes to your database. Compares the configuration with the existing database schema and reports warnings.
- any other value - does nothing
Más sobre dbCreate
Hibernate puede crear automáticamente las tablas de base de datos necesarias para su modelo de dominio. Tiene algún control sobre cuándo y cómo lo hace a través de la propiedaddbCreate, que puede tomar estos valores:
- create - borra la estructura vigente el esquema en el inicio, borrando tablas, índices, etc. primero.
- create-drop - igual que create, pero también borra las tablas cuando se cierra la aplicación sin errores.
- update - crea las tablas e índices que faltan y actualiza el esquema actual sin perder datos ni las tablas. Tenga en cuenta que esto no puede manejar correctamente muchos cambios en el esquema como cambios de nombre de columna (te dejan la antigua columna que contiene los datos existentes).
- validate - no modifica la base de datos. Compara la configuración con el esquema de base de datos existente y las reporta los avisos.
- cualquier otro valor - no hace nada
You can also remove the
También puede quitar el parámetro dbCreate setting completely, which is recommended once your schema is relatively stable and definitely when your application and database are deployed in production. Database changes are then managed through proper migrations, either with SQL scripts or a migration tool like Liquibase (the Database Migration plugin uses Liquibase and is tightly integrated with Grails and GORM).
dbCreate, que es lo recomendado una vez que su esquema es relativamente estable y definitivamente cuando su base de datos y aplicaciones se implementan en producción. Los cambios de la base de datos son administrados a través de las migraciones adecuadas, con secuencias de comandos SQL o una herramienta de migración como Liquibase (el plugin Database Migration utiliza Liquibase y está estrechamente integrado con Grails y GORM).
3.3.1 Orígenes de datos y entornos
The previous example configuration assumes you want the same config for all environments: production, test, development etc.Grails' DataSource definition is "environment aware", however, so you can do:
La configuración del ejemplo anterior asume que desea la misma configuración para todos los entornos: producción, pruebas, desarrollo, etc..La definición de origen de datos de Grails es sensible al entorno, por lo que puedes hacer o siguiente:dataSource {
pooled = true
driverClassName = "com.mysql.jdbc.Driver"
dialect = org.hibernate.dialect.MySQL5InnoDBDialect
// other common settings here
}environments {
production {
dataSource {
url = "jdbc:mysql://liveip.com/liveDb"
// other environment-specific settings here
}
}
}3.3.2 Orígenes de datos JNDI
Referring to a JNDI DataSource
Most Java EE containers supplyDataSource instances via Java Naming and Directory Interface (JNDI). Grails supports the definition of JNDI data sources as follows:Utilizando un origen de datos JNDI
La mayoría de los contenedores J2EE proporcionan instancias deDataSource a través de Java Naming and Directory Interface (JNDI). Grails es compatible con la definición de orígenes de datos JNDI como sigue:dataSource {
jndiName = "java:comp/env/myDataSource"
}The format on the JNDI name may vary from container to container, but the way you define the
El formato del nombre JNDI puede variar de un contenedor a otro, pero la manera de definir el DataSource in Grails remains the same.Configuring a Development time JNDI resource
The way in which you configure JNDI data sources at development time is plugin dependent. Using the Tomcat plugin you can define JNDI resources using thegrails.naming.entries setting in grails-app/conf/Config.groovy:DataSource en Grails sigue siendo la misma.Configuración de un recurso JNDI de tiempo de desarrollo
La forma en que puede configurar orígenes de datos JNDI al tiempo de desarrollo depende del plugin utilizado. Utilizando el plugin de Tomcat plugin puede definir recursos JNDI mediantegrails.naming.entries en grails-app/conf/Config.groovy:grails.naming.entries = [
"bean/MyBeanFactory": [
auth: "Container",
type: "com.mycompany.MyBean",
factory: "org.apache.naming.factory.BeanFactory",
bar: "23"
],
"jdbc/EmployeeDB": [
type: "javax.sql.DataSource", //required
auth: "Container", // optional
description: "Data source for Foo", //optional
driverClassName: "org.h2.Driver",
url: "jdbc:h2:mem:database",
username: "dbusername",
password: "dbpassword",
maxActive: "8",
maxIdle: "4"
],
"mail/session": [
type: "javax.mail.Session,
auth: "Container",
"mail.smtp.host": "localhost"
]
]3.3.3 Migraciones automáticas de bases de datos
The
La propiedad dbCreate property of the DataSource definition is important as it dictates what Grails should do at runtime with regards to automatically generating the database tables from GORM classes. The options are described in the DataSource section:
createcreate-dropupdatevalidate- no value
dbCreate is by default set to "create-drop", but at some point in development (and certainly once you go to production) you'll need to stop dropping and re-creating the database every time you start up your server.dbCreate de la definición del DataSource es importante ya que dicta lo que debe hacer Grails en tiempo de ejecución con respecto a la generación automática de las tablas de base de datos de clases GORM. Las opciones se describen en la sección DataSource:
createcreate-dropupdatevalidate- no value
dbCreate es por defecto "create-drop" (borrar y crear), pero en algún punto en el desarrollo (y, desde luego, una vez pase a la producción) deberá dejar de borrar y volver a crear la base de datos cada vez que inicie el servidor.It's tempting to switch to
Es tentador cambiar a update so you retain existing data and only update the schema when your code changes, but Hibernate's update support is very conservative. It won't make any changes that could result in data loss, and doesn't detect renamed columns or tables, so you'll be left with the old one and will also have the new one.Grails supports Rails-style migrations via the Database Migration plugin which can be installed by running
grails install-plugin database-migrationThe plugin uses Liquibase and and provides access to all of its functionality, and also has support for GORM (for example generating a change set by comparing your domain classes to a database).
update (actualizar) para mantener los datos existentes y sólo actualizar el esquema cuando el código cambia, pero el soporte de actualización de Hibernate es muy conservador. No realizar los cambios que podrían dar lugar a pérdida de datos y no detecta renombrado de columnas o tablas, por lo que quedará con el viejo y también con el nuevo.Grails soporta migraciones estilo Rails a través del plugin Database Migration plugin que puede instalarse mediante la ejecución de
grails install-plugin database-migrationEl plugin utiliza Liquibase y proporciona acceso a toda su funcionalidad y también cuenta con soporte para GORM (por ejemplo generando un cambio comparando sus clases de dominio con una base de datos).
3.3.4 Proxy de origen de datos preparado para transacción
The actual
El dataSource bean is wrapped in a transaction-aware proxy so you will be given the connection that's being used by the current transaction or Hibernate Session if one is active.If this were not the case, then retrieving a connection from the dataSource would be a new connection, and you wouldn't be able to see changes that haven't been committed yet (assuming you have a sensible transaction isolation setting, e.g. READ_COMMITTED or better).The "real" unproxied dataSource is still available to you if you need access to it; its bean name is dataSourceUnproxied.You can access this bean like any other Spring bean, i.e. using dependency injection:
dataSource bean está envuelto en un proxy preparado para la transacción por lo que se le dará la conexión que se utiliza en la transacción actual o la Session Hibernate si está activa.Si esto no fuera el caso, entonces recuperar una conexión desde el datasource sería una nueva conexión, y no sería capaz de ver los cambios que no hayan sido comprometidos aún (suponiendo que tiene un aislamiento de transacción razonable, por ejemplo, READ_COMMITTED o mejor).El dataSource real fuera del proxy sigue estando disponible si necesita tener acceso a él; su nombre de bean es dataSourceUnproxied.Se puede acceder a este bean como a cualquier otro bean de Spring, es decir, mediante inyección de dependencias:class MyService { def dataSourceUnproxied
…
}
or by pulling it from the
o solicitándolo al ApplicationContext:
ApplicationContext:def dataSourceUnproxied = ctx.dataSourceUnproxied
3.3.5 La consola de la Base de Datos
The H2 database console is a convenient feature of H2 that provides a web-based interface to any database that you have a JDBC driver for, and it's very useful to view the database you're developing against. It's especially useful when running against an in-memory database.
La consola de base de datos H2 es una práctica función de H2 que proporciona una interfaz basada en web para cualquier base de datos que tenga un driver JDBC, y es muy útil para ver la base de datos contra la que se está desarrollando. Es especialmente útil cuando se ejecuta contra una base de datos en memoria.
You can access the console by navigating to http://localhost:8080/appname/dbconsole in a browser. The URI can be configured using the
Para acceder a la consola, vaya a la dirección http://localhost:8080/appname/dbconsole en un navegador. La URI se puede configurar mediante el atributo grails.dbconsole.urlRoot attribute in Config.groovy and defaults to '/dbconsole'.
grails.dbconsole.urlRoot en el Config.groovy y por defecto es '/dbconsole'.
The console is enabled by default in development mode and can be disabled or enabled in other environments by using the
La consola está activada por defecto en el modo de desarrollo y puede ser activada o desactivada en otros ambientes mediante el uso del atributo grails.dbconsole.enabled attribute in Config.groovy. For example you could enable the console in production using
grails.dbconsole.enabled en el Config.groovy. Por ejemplo, podría habilitar la consola en la producción así:environments {
production {
grails.serverURL = "http://www.changeme.com"
grails.dbconsole.enabled = true
grails.dbconsole.urlRoot = '/admin/dbconsole'
}
development {
grails.serverURL = "http://localhost:8080/${appName}"
}
test {
grails.serverURL = "http://localhost:8080/${appName}"
}
}If you enable the console in production be sure to guard access to it using a trusted security framework.
Configuration
By default the console is configured for an H2 database which will work with the default settings if you haven't configured an external database - you just need to change the JDBC URL tojdbc:h2:mem:devDB. If you've configured an external database (e.g. MySQL, Oracle, etc.) then you can use the Saved Settings dropdown to choose a settings template and fill in the url and username/password information from your DataSource.groovy.
Si habilita la consola en producción asegúrese de proteger el acceso a ella mediante un framework de seguridad de confianza.
Configuración
Por defecto, la consola está configurada para una base de datos H2 que funciona con la configuración predeterminada si no ha configurado una base de datos externa; basta con cambiar la URL JDBC ajdbc:h2:mem:devDB. Si ha configurado una base de datos externa (por ejemplo, MySQL, Oracle, etc.) puede utilizar la lista desplegable de Saved Settings para seleccionar una plantilla y rellenar la url, y el nombre de usuario y contraseña de tu DataSource.groovy.
3.3.6 Orígenes de datos multiples
By default all domain classes share a single
Por defecto, todas las clases de dominio compartan un solo DataSource and a single database, but you have the option to partition your domain classes into two or more DataSources.Configuring Additional DataSources
The defaultDataSource configuration in grails-app/conf/DataSource.groovy looks something like this:
DataSource y una única base de datos, pero tiene la opción de dividir las clases de dominio en dos o más DataSources.Configuración de orígenes de datos adicionales
La configuración delDataSource por defecto en grails-app/conf/DataSource.groovy es algo como esto:dataSource {
pooled = true
driverClassName = "org.h2.Driver"
username = "sa"
password = ""
}
hibernate {
cache.use_second_level_cache = true
cache.use_query_cache = true
cache.provider_class = 'net.sf.ehcache.hibernate.EhCacheProvider'
}environments {
development {
dataSource {
dbCreate = "create-drop"
url = "jdbc:h2:mem:devDb"
}
}
test {
dataSource {
dbCreate = "update"
url = "jdbc:h2:mem:testDb"
}
}
production {
dataSource {
dbCreate = "update"
url = "jdbc:h2:prodDb"
}
}
}
This configures a single
Esto configura un único DataSource with the Spring bean named dataSource. To configure extra DataSources, add another dataSource block (at the top level, in an environment block, or both, just like the standard DataSource definition) with a custom name, separated by an underscore. For example, this configuration adds a second DataSource, using MySQL in the development environment and Oracle in production:
DataSource con un bean de Spring llamado dataSource. Para configurar DataSources adicionales, agregue otro bloque dataSource (en el nivel superior, en un bloque de entorno, o ambos, al igual que la definición estándar de DataSource) con un nombre personalizado, separado por un guión bajo. Por ejemplo, esta configuración agrega un segundo DataSource, usando MySQL en el entorno de desarrollo y Oracle en producción:environments {
development {
dataSource {
dbCreate = "create-drop"
url = "jdbc:h2:mem:devDb"
}
dataSource_lookup {
dialect = org.hibernate.dialect.MySQLInnoDBDialect
driverClassName = 'com.mysql.jdbc.Driver'
username = 'lookup'
password = 'secret'
url = 'jdbc:mysql://localhost/lookup'
dbCreate = 'update'
}
}
test {
dataSource {
dbCreate = "update"
url = "jdbc:h2:mem:testDb"
}
}
production {
dataSource {
dbCreate = "update"
url = "jdbc:h2:prodDb"
}
dataSource_lookup {
dialect = org.hibernate.dialect.Oracle10gDialect
driverClassName = 'oracle.jdbc.driver.OracleDriver'
username = 'lookup'
password = 'secret'
url = 'jdbc:oracle:thin:@localhost:1521:lookup'
dbCreate = 'update'
}
}
}
You can use the same or different databases as long as they're supported by Hibernate.
Puede utilizar las mismos o diferentes bases de datos siempre y cuando esté soportadas por Hibernate.Configuring Domain Classes
If a domain class has noDataSource configuration, it defaults to the standard 'dataSource'. Set the datasource property in the mapping block to configure a non-default DataSource. For example, if you want to use the ZipCode domain to use the 'lookup' DataSource, configure it like this;
Configuración de clases de dominio
Si una clase de dominio no tiene ninguna configuración deDataSource, utiliza el 'dataSource' estándar. Debe establecer la propiedad datasource en el bloque mapping para configurar otro DataSource. Por ejemplo, si desea que el dominio ZipCode utilice el DataSource 'lookup', configurelo así:class ZipCode { String code static mapping = {
datasource 'lookup'
}
}
A domain class can also use two or more
Una clase de dominio también puede utilizar dos o más DataSources. Use the datasources property with a list of names to configure more than one, for example:
DataSources. Use la propiedad datasources con una lista de nombres para configurar más de uno, por ejemplo:class ZipCode { String code static mapping = {
datasources(['lookup', 'auditing'])
}
}
If a domain class uses the default
Si una clase de dominio utiliza el DataSource and one or more others, use the special name 'DEFAULT' to indicate the default DataSource:
DataSource por defecto y algún o algunos otros, utilice el nombre especial 'DEFAULT' para indicar el DataSource por defecto:class ZipCode { String code static mapping = {
datasources(['lookup', 'DEFAULT'])
}
}
If a domain class uses all configured
Si una clase de dominio utiliza todos los DataSources use the special value 'ALL':
DataSources configurados use el valor especial 'ALL':class ZipCode { String code static mapping = {
datasource 'ALL'
}
}Namespaces and GORM Methods
If a domain class uses more than oneDataSource then you can use the namespace implied by each DataSource name to make GORM calls for a particular DataSource. For example, consider this class which uses two DataSources:
Espacios de nombres y métodos GORM
Si una clase de dominio utiliza más de unDataSource puede utilizar el espacio de nombres que implica cada nombre de DataSource para hacer llamadas GORM para un determinado DataSource. Por ejemplo, esta clase que utiliza dos DataSources:class ZipCode { String code static mapping = {
datasources(['lookup', 'auditing'])
}
}
The first As you can see, you add the
El primer DataSource specified is the default when not using an explicit namespace, so in this case we default to 'lookup'. But you can call GORM methods on the 'auditing' DataSource with the DataSource name, for example:def zipCode = ZipCode.auditing.get(42) … zipCode.auditing.save()
DataSource to the method call in both the static case and the instance case.
DataSource especificado es el valor por defecto cuando no se utiliza un espacio de nombre explícito, por lo que en este caso el predeterminado es 'lookup'. Pero puede llamar a métodos GORM con el DataSource con nombre del DataSource, por ejemplo:def zipCode = ZipCode.auditing.get(42) … zipCode.auditing.save()
DataSource a la llamada de método tanto en el caso de llamada estática como en el caso de la instancia.Services
Like Domain classes, by default Services use the defaultDataSource and PlatformTransactionManager. To configure a Service to use a different DataSource, use the static datasource property, for example:
Servicios
Como las clases de dominio, los servicios utilizan elDataSource por defecto y el PlatformTransactionManager. Para configurar un servicio para que utilice un DataSource diferente , utilice la propiedad estática datasource, por ejemplo:class DataService { static datasource = 'lookup' void someMethod(...) {
…
}
}
A transactional service can only use a single
Un servicio transaccional puede sólo utilizar un único DataSource, so be sure to only make changes for domain classes whose DataSource is the same as the Service.Note that the datasource specified in a service has no bearing on which datasources are used for domain classes; that's determined by their declared datasources in the domain classes themselves. It's used to declare which transaction manager to use.What you'll see is that if you have a Foo domain class in dataSource1 and a Bar domain class in dataSource2, and WahooService uses dataSource1, a service method that saves a new Foo and a new Bar will only be transactional for Foo since they share the datasource. The transaction won't affect the Bar instance. If you want both to be transactional you'd need to use two services and XA datasources for two-phase commit, e.g. with the Atomikos plugin.DataSource, así que asegúrese de sólo hacer cambios para las clases de dominio cuyos DataSource es el mismo que el del servicio.Tenga en cuenta que la fuente de datos que se especifica en un servicio no tiene relación con las fuentes de datos que se utilizan para las clases de dominio, que son determinadas por los orígenes de datos declarados en las clases de dominio. Se utiliza para declarar que administrador de transacciones se utilizará.Lo que verá es que si usted tiene una clase de dominio Foo en un DataSource1 y una clase de dominio Bar en el dataSource2 y un servicio WahooService utiliza el DataSource1, un método del servicio que salva un nuevo Foo y un nuevo Bar sólo será transaccional para Foo, ya que comparten la fuente de datos, y la operación no afectará a la instancia de Bar. Si quieres ser transaccional para ambas instancias tendrá que utilizar dos servicios y fuentes de datos con commit en dos fases, por ejemplo, con el plugin Atomikos.XA and Two-phase Commit
Grails has no native support for XADataSources or two-phase commit, but the Atomikos plugin makes it easy. See the plugin documentation for the simple changes needed in your DataSource definitions to reconfigure them as XA DataSources.XA y commit en dos fases
Grails no tiene soporte nativo paraDataSources XA o commit en dos fases, pero el plugin Atomikos hace que sea fácil. Consulte la documentación de plugin para conocer los cambios que debe hacer en la definición de su DataSource para configurarlos como DataSources XA.

