12

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

这个问题是我最接近一段有用的代码,但这并不是我所需要的。

问题 #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

  • 如果我将所有数据源声明为Datasource.groovy文件的一部分,那么我可以对所有数据库执行操作,但不像文档所宣传的那样

如果我对我的域对象进行静态映射,它会起作用:

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. (这将是一个非常棒的额外内容,作为“顶部的樱桃”)成功使用多个数据源和 Spring 安全核心?如何切换安全插件的数据源?

谢谢

--

4

4 回答 4

1

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

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

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 查询。是类文档。sql.execute "SQL STATEMENT"sqlSql

于 2015-05-15T01:49:28.947 回答
1

我有两个使用 Grails 2.3.11 的不同数据源。我将 1 个数据源用于我的 H2 数据库,另一个用于 Oracle 数据库。我不得不将 Hibernate 4 与 Grails 2.3 一起使用。在我的BuildConfig.groovy我指定了对休眠 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 中”。在https://jira.grails.org/browse/GPCACHEEHCACHE- 13,但是一旦我将设置到位,错误就消失了。)

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

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
            }
        }
    }
}

默认情况下,我的域类使用 H2 数据库,并将我的 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 注入我的其他数据源。


我无法让这两个数据源按照 http://grails.github.io/grails-doc/2.3.11/guide/conf.html#multipleDatasources 文档中的说明工作。通过将数据源声明为 dataSource 和 dataSource_lookup 然后将其用作:

class DataService {
   static datasource = 'lookup'

   void someMethod(...) {
      …
   }
} 

我能够使用上述解决方案使其工作


于 2016-03-17T14:58:33.350 回答
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();

然后可以使用连接对象。

我认为应该有帮助

于 2013-06-11T07:37:04.403 回答
0

为 grails 使用分片插件来解决您的问题

于 2014-07-27T12:10:53.243 回答