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



我正在开发一个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 安全核心的多个数据源?如何切换安全插件的数据源?

谢谢

--

我有两个不同的数据源使用Grails 2.3.11。我正在为我的 H2 数据库使用 1 个数据源,将另一个数据源用于 Oracle 数据库。我不得不将Hibernate 4与Grails 2.3一起使用。在我的BuildConfig.groovy中,我指定了对休眠 4 的依赖关系:

runtime ":hibernate4:4.3.5.4"

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

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
}

(旁注:如果没有缓存设置,我会收到以下缓存管理器错误,"同一虚拟机中已存在另一个未命名的缓存管理器"。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 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)
        ...
    }
}

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


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

class DataService {
   static datasource = 'lookup'
   void someMethod(...) {
      …
   }
} 

但我能够让它与上述解决方案一起工作


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

我实现了它,连接到应用程序中的每个数据源(不是来自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.execute "SQL STATEMENT"执行 SQL 查询并关闭sql连接。这是Sql类文档。

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

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

首次导入基本数据源

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();

然后可以使用连接对象。

我认为它应该有所帮助

使用分

片插件来解决您的问题

最新更新