Grails 2服务中的多个动态数据源

时间:2012-06-01 21:36:21

标签: grails datasource

我正在使用Grails应用程序,我必须访问多个数据源。数据源在默认数据库中定义(即它们存储在那里,我必须调用默认数据库来检索我必须准备连接的数据源名称列表)。当服务器启动时,我检索数据库列表,创建数据源bean并注入它们。所有动态添加的数据库在结构上都是相同的(即具有相同的表和域对象结构)。

This question是我最接近一段有用的代码,但它并不是我需要的。

问题#1

  • 当我注册数据源bean时,它们会出现在我期望的位置,但是Grails不会把它们拿起来。

这是我添加它们的方式:

// Register datasource bean
def beanName = 'dataSource_devDB1'

BeanBuilder bb = new BeanBuilder()
bb.beans {
    "${beanName}"(BasicDataSource) { 
        url = "jdbc:h2:devDB1Db;MVCC=TRUE"
        pooled = true
        driverClassName = "org.h2.Driver"
        username = "sa"
        password = ""            
    }
}

bb.registerBeans(grailsApplication.mainContext)

// check that it registered
def ctx = grailsApplication.mainContext
def ctxlist = ctx2.beanDefinitionNames.findAll{it.contains( 'dataSource' )}

log.info "ctxlist = " + ctxlist

打印:

[dataSource, dataSourceUnproxied, dataSource_devDB1]

当我这样做时,我可以对默认数据源执行操作,就是这样。

问题#2

如果我在域对象上进行静态映射,它就可以工作:

static mapping = {datasources(['devDB1', 'devDB2', 'DEFAULT')] or datasource = 'ALL'

但我想要的是将所有这些作为服务的一部分执行,并声明我的域对象使用所有数据源。

声明服务中的数据源无效:

class secureDBService{

  static datasource = "devDB1"

  def readWriteMethod(){
   .....
  // this always uses the default datasource ignoring the static property above.
  // the only time it uses devDB1 is if I declare it as part of the domain datasource
  // mapping
  }
}

无论如何,这将始终使用默认数据源。它使用正确数据源的唯一时间是在域对象上我列出了有问题的数据源。


所以,有人:

  1. 尝试添加动态数据源并成功了吗?

  2. 使用grails服务在数据源之间切换?

  3. (这将是一个非常棒的额外,作为“樱桃在上面”)成功使用多个数据源与弹簧安全核心?如何切换安全插件的数据源?

  4. 由于

    -

4 个答案:

答案 0 :(得分:1)

我参与了类似的项目,其中应用程序必须从默认数据库中检索数据源列表(连接字符串),并连接到每个数据源并使用quartz作业执行操作。

我实现了它,连接到应用程序中的每个数据源(而不是来自 DataSorce.groovy )并编写SQL而不是Hah。

import groovy.sql.Sql

class SqlService{
    Sql getDbConnection(String connectionString, String dbUser, String dbPassword){
        def sql = Sql.newInstance(connectionString, dbUser, dbPassword, "driver_class")
        return sql
    }
}

从上面的代码获取sql连接并使用sql.execute "SQL STATEMENT"执行SQL查询并关闭sql连接。 HereSql类文档。

答案 1 :(得分:1)

我有两个不同的数据源使用Grails 2.3.11。我为H2数据库使用了1个数据源,为Oracle数据库使用了另一个数据源。我不得不使用带有Grails 2.3的Hibernate 4。在我的BuildConfig.groovy我指定了对hibernate 4的依赖:

runtime ":hibernate4:4.3.5.4"

在我的DataSource.groovy文件中,我使用了以下Hibernate缓存设置:

hibernate {
    cache.use_second_level_cache = true
    cache.use_query_cache = false
    cache.region.factory_class = 'org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory'
    singleSession = true // configure OSIV singleSession mode
}

(侧面注意:没有缓存设置,我得到了以下CacheManager错误,"另一个未命名的CacheManager已存在于同一个VM"。有一个关于此问题的开放式错误报告{{ 3}},但是一旦我将设置放到位,错误就消失了。)

然后我定义了我的数据源:

environments {
    development {
        dataSource_oracle {
            pooled = true
            dialect = org.hibernate.dialect.Oracle10gDialect
            driverClassName = 'oracle.jdbc.OracleDriver'
            username = 'user'
            password = 'pass'
            url = 'jdbc:oracle:thin:@(serverName):(port):(SID)'
            dbCreate = 'validate'
        }
        dataSource {
            dbCreate = "update"
            url = "jdbc:h2:devDb;MVCC=TRUE;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE"
            properties {
               jmxEnabled = true
               initialSize = 5
               maxActive = 50
               minIdle = 5
               maxIdle = 25
               maxWait = 10000
               maxAge = 10 * 60000
               timeBetweenEvictionRunsMillis = 5000
               minEvictableIdleTimeMillis = 60000
               validationQuery = "SELECT 1"
               validationQueryTimeout = 3
               validationInterval = 15000
               testOnBorrow = true
               testWhileIdle = true
               testOnReturn = false
               jdbcInterceptors = "ConnectionState"
               defaultTransactionIsolation = java.sql.Connection.TRANSACTION_READ_COMMITTED
            }
        }
    }
}

默认情况下,我的Domain类使用H2 db,我将Oracle数据源指定为:

class MyService {

    def dataSource_oracle
    static transactional = true

    def getMethod() {
        assert dataSource_oracle != null, "dataSource is null! Please check your configuration!"
        def sql = Sql.newInstance(dataSource_oracle)
        ...
    }
}

上面,我允许依赖注入为服务提供oracle数据源def dataSource_oracle。如果我想使用H2数据源,我将数据源声明为def dataSource并允许DI注入我的其他数据源。

我无法按照https://jira.grails.org/browse/GPCACHEEHCACHE-13文档中的说明使两个数据源正常工作。通过将数据源声明为dataSource和dataSource_lookup,然后将其用作:

class DataService {
   static datasource = 'lookup'

   void someMethod(...) {
      …
   }
} 

但是我能够使用上述解决方案

答案 2 :(得分:0)

您可以在单个应用程序中添加多个数据源,并在服务中访问它们。

首先,您需要在resources.groovy中添加基本数据源。

首先导入BasicDataSource

import org.apache.commons.dbcp.BasicDataSource;

然后

    switch (grails.util.GrailsUtil.environment) {
    case "development":
        firstDataSource( BasicDataSource ) {
            driverClassName = "net.sourceforge.jtds.jdbc.Driver"
            url = "jdbc:jtds:sqlserver://localhost:1433;DatabaseName=<Db_name>"
            username = "sa"
            password = "root"
            String SqlServerInstance = "SQLEXPRESS";
            url = url + ";" + SqlServerInstance;
        }
        break

    case "test":
        firstDataSource( BasicDataSource ) {

            driverClassName = "net.sourceforge.jtds.jdbc.Driver"
            url = "jdbc:jtds:sqlserver://localhost:1433;DatabaseName=<Db_name>"
            username = "sa"
            password = "root"
            String SqlServerInstance = "SQLEXPRESS";
            url = url + ";" + SqlServerInstance;            }
        break;

}

以相同的方式添加更多数据源,上面的代码将为您提供一个除默认数据源之外的其他数据源。 我使用switch为不同的环境配置相同的数据源,同样可以添加更多的数据源。

在服务中,它可以在服务中访问:

BasicDataSource firstDataSource;
Connection con = firstDataSource.getConnection();

然后可以使用连接对象。

我认为应该有所帮助

答案 3 :(得分:0)

为将解决您的问题的Grails使用分片插件