Grails 2服务中的多个动态数据源 [英] Grails 2 multiple dynamic datasources in services

查看:94
本文介绍了Grails 2服务中的多个动态数据源的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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



问题#1




  • 当我注册数据源bean时,它们显示出我期望的位置,但

  • $ b

    这是我添加它们的方式:

    < pre $ //注册数据源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(grails Application.mainContext)

    //检查它是否已注册
    def ctx = grailsApplication.mainContext
    def ctxlist = ctx2.beanDefinitionNames.findAll {it.contains('dataSource')}

    log.infoctxlist =+ ctxlist

    / p>

      [dataSource,dataSourceUnproxied,dataSource_devDB1] 

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



    问题#2




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



    如果我在我的域对象上执行静态映射,它将起作用:

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

    但是我想要的是执行所有这些,并声明我的域对象使用所有数据源。



    声明服务中的数据源不起作用:

      class secureDBService {

    static datasource =devDB1

    def readWriteMethod(){
    ... ..
    //这总是使用默认的数据源,忽略上面的静态属性。
    //它使用devDB1的唯一时间是如果我将它声明为域数据源的一部分
    //映射
    }
    }

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






    所以,有任何人:


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

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


    3. (这将是一个非常棒的额外工具,因为顶级樱桃)使用多个数据源用弹簧安全核心?如何切换安全插件的数据源?




    4. 谢谢

      -

      解决方案

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

       运行时:hibernate4:4.3.5.4

      在我的 DataSource.groovy file我使用了下面的Hibernate缓存设置:
      $ b $ $ p $ h $ {
      cache.use_second_level_cache = true
      cache.use_query_cache = false
      cache.region.factory_class ='org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory'
      singleSession = true //配置OSIV singleSession模式
      } $ b (SIDE注意:没有缓存设置,我得到了下面的CacheManager错误,另一个未命名的CacheManager已经存在于$ c $ b $ / pre
      $ b $同一个虚拟机。在 https://jira.grails.org/上有一个关于此的开放式错误报告。浏览/ 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
      mi nEvictableIdleTimeMillis = 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数据库,并指定我的Oracle数据源为:

        class MyService {

      def dataSource_oracle
      static transactional = true
      $ b $ get getMethod(){
      assert dataSource_oracle!= null,dataSource为null!请检查您的配置!
      def sql = Sql.newInstance(dataSource_oracle)
      ...
      }
      }
      def dataSource_oracle 。如果我想要为了使用H2数据源,我声明数据源为 def dataSource 并允许DI注入我的其他数据源。






      我无法按照中的说明使两个数据源正常工作-doc / 2.3.11 / guide / conf.html#multipleDatasourcesrel =nofollow> http://grails.github.io/grails-doc/2.3.11/guide/conf.html#multipleDatasources 。通过声明数据源为dataSource和dataSource_lookup,然后使用它:

        class DataService {
      static datasource ='lookup '

      void someMethod(...){
      ...
      }
      }

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





      I am working on a Grails application where I must access several datasources. The datasources are defined in the default database (ie. they are stored there and I must make a call to the default database to retrieve a list of the datasource names I must prepare to connect to). When the server boots up I retrieve the list of databases, create the datasource beans and inject them. All dynamically added databases are structurally identical (ie. have the same table and domain object structure).

      This question is the closest I got to a useful piece of code, but it's not quite what I need.

      Issue #1

      • When I register the datasource beans, they show up where I expect, but Grails does not pick them up.

      This is how I add them:

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

      This prints:

      [dataSource, dataSourceUnproxied, dataSource_devDB1]
      

      When I do this, I can execute operations on the default datasource, and that's it.

      Issue #2

      It works if I do the static mapping on my domain objects:

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

      but what I want is to perform all this as part of a service, and declaring my domain objects to use ALL datasources.

      Declaring the datasource in the service is not working:

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

      This will always use the default datasource no matter what. The only time when it uses the correct datasource is if on the domain object I list the datasource in question.


      So, has anyone:

      1. tried adding dynamic datasources and succeeded?

      2. switched between datasources using grails services?

      3. (and this would be a fantastic extra , as a "cherry on top") had success using multiple datasource with spring security core? How do you switch the datasource for the security plugin?

      Thanks

      --

      解决方案

      I've got two different datasources working with Grails 2.3.11. I'm using 1 datasource for my H2 database and another for an Oracle db. I had to use Hibernate 4 with Grails 2.3. In my BuildConfig.groovy I specified the dependency on hibernate 4:

      runtime ":hibernate4:4.3.5.4"
      

      In my DataSource.groovy file I used the following Hibernate caching settings:

      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
      }
      

      (SIDE NOTE: without the cache settings, I was getting following CacheManager error, "Another unnamed CacheManager already exists in the same VM". There's an open bug report on this at https://jira.grails.org/browse/GPCACHEEHCACHE-13, but once I put the settings in place the error was gone.)

      then I defined my datasources:

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

      By default, my Domain classes use the H2 db and I specify my Oracle datasource as:

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

      Above, I allow the dependency injection to provide the service with the oracle datasource, def dataSource_oracle. If I want to use the H2 datasource, I declare the datasource as def dataSource and allow the DI to inject my other datasource.


      I could not get the two datasources to work as specified in the documentation at http://grails.github.io/grails-doc/2.3.11/guide/conf.html#multipleDatasources. By declaring the datasources as dataSource and dataSource_lookup then using it as:

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

      but I was able to get it working with the solution described above.


      这篇关于Grails 2服务中的多个动态数据源的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆