(Quick Reference)

3.3.6 Orígenes de datos multiples - Reference Documentation

Authors: Graeme Rocher, Peter Ledbrook, Marc Palmer, Jeff Brown, Luke Daley, Burt Beckwith

Version: null

3.3.6 Orígenes de datos multiples

By default all domain classes share a single DataSource and a single database, but you have the option to partition your domain classes into two or more DataSources.

Configuring Additional DataSources

The default DataSource configuration in grails-app/conf/DataSource.groovy looks something like this:

Por defecto, todas las clases de dominio compartan un solo 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 del DataSource 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 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:

Esto configura un único 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.

Configuring Domain Classes

If a domain class has no DataSource 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;

Puede utilizar las mismos o diferentes bases de datos siempre y cuando esté soportadas por Hibernate.

Configuración de clases de dominio

Si una clase de dominio no tiene ninguna configuración de DataSource, 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 DataSources. Use the datasources property with a list of names to configure more than one, for example:

Una clase de dominio también puede utilizar dos o más 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 DataSource and one or more others, use the special name 'DEFAULT' to indicate the default DataSource:

Si una clase de dominio utiliza el 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 DataSources use the special value 'ALL':

Si una clase de dominio utiliza todos los 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 one DataSource 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 un DataSource 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 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()

As you can see, you add the DataSource to the method call in both the static case and the instance case.

El primer 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()

Como puede ver, agrega el 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 default DataSource 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 el DataSource 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 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.

Un servicio transaccional puede sólo utilizar un único 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 XA DataSources 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 para DataSources 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.