3.3.6 多数据源 - Reference Documentation
Authors: Graeme Rocher, Peter Ledbrook, Marc Palmer, Jeff Brown, Luke Daley, Burt Beckwith
Version: null
3.3.6 多数据源
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.
DataSource和数据库,但是你还是有将领域类拆分到两个甚至更多个DataSource的选择的。Configuring Additional DataSources
The defaultDataSource configuration in grails-app/conf/DataSource.groovy looks something like this: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"
}
}
}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: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'
}
}
}配置额外的数据源
缺省的DataSource配置是位于grails-app/conf/DataSource.groovy中的,大体样子如下: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"
}
}
}dataSource的DataSource。要配置额外的DataSource,需要增加另外一个自定义名称(以下划线分割)的dataSource(跟标准的DataSource类似,只不过要定义在在最外层、环境代码块或者同时两个地方)代码块即可。例如,以下代码的配置新增了第二个DataSource,其在开发环境下是MySQL数据库,在生产环境下是Oracle: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'
}
}
}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;class ZipCode { String code static mapping = {
datasource 'lookup'
}
}DataSources. Use the datasources property with a list of names to configure more than one, for example:class ZipCode { String code static mapping = {
datasources(['lookup', 'auditing'])
}
}DataSource and one or more others, use the special name 'DEFAULT' to indicate the default DataSource:class ZipCode { String code static mapping = {
datasources(['lookup', 'DEFAULT'])
}
}DataSources use the special value 'ALL':class ZipCode { String code static mapping = {
datasource 'ALL'
}
}配置领域类
如果一个领域类没有配置DataSource,那么其缺省使用标准的'dataSource'。你可以在mapping代码块中设置datasource属性来配置一个非标准的DataSource。例如,你希望ZipCode使用名为'lookup'的DataSource,其配置如下:class ZipCode { String code static mapping = {
datasource 'lookup'
}
}DataSources。这时候,只需要将datasources设置为一个名称的列表即可,比如:class ZipCode { String code static mapping = {
datasources(['lookup', 'auditing'])
}
}DataSource,可以使用名称为'DEFAULT'来代表缺省的DataSource:class ZipCode { String code static mapping = {
datasources(['lookup', 'DEFAULT'])
}
}DataSource,请使用特定名称'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:class ZipCode { String code static mapping = {
datasources(['lookup', 'auditing'])
}
}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.
命名空间和GORM方法
如果一个领域类使用了多于一个的DataSource,你可以将其每个DataSource名称作为命名空间,并且以此命名来执行GORM的方法调用。例如,下面示例的类有两个DataSource:class ZipCode { String code static mapping = {
datasources(['lookup', 'auditing'])
}
}DataSource被视为缺省,上例中其缺省命名空间是'lookup'。但是你也可以在'auditing'的DataSource上执行GORM方法,比如:def zipCode = ZipCode.auditing.get(42) … zipCode.auditing.save()
DataSource上进行静态和实例类型的方法调用。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:class DataService { static datasource = 'lookup' void someMethod(...) {
…
}
}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和PlatformTransactionManager。要配置服务使用另外一个不同的DataSource,请使用静态的(static)datasource属性,比如:class DataService { static datasource = 'lookup' void someMethod(...) {
…
}
}DataSource,因此请确保领域类的DataSource的名字要跟服务类中定义的一致。注意,一个服务类的datasource不对领域类的datasources产生影响,后者由其自身的声明决定。服务类的datasource多用来声明要使用哪一个事务管理器。假设你有两个数据源,领域类Foo属于dataSource1,Bar属于dataSource2,而WahooService使用dataSource1,此外还有一个方法来实现Foo和Bar的新增保存,那么只有Foo是支持事务的,因为他们共享dataSource1数据源。而Bar实例并不受事务影响。如果你想两者都支持事务,那么你需要两个服务类和支持两阶段提交的XA数据源,比如使用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和两阶段(Two-phase)提交
Grails并没有直接支持XADataSources 或者 两阶段提交,但是Atomikos 插件使两者变得容易。此插件的文档有介绍如何比较容易的将现有的DataSource定义重新配置为XA DataSources。

