【问题标题】:grails how to (re) connect to a second databasegrails 如何(重新)连接到第二个数据库
【发布时间】:2014-05-24 05:22:00
【问题描述】:

我们有一个 grails 应用程序,它在 grails 数据库中存储了各种域对象。该应用程序连接到第二个数据库,运行一些原始 sql,并在表中显示结果。它基本上是一个报告服务器。

我们通过在 DataSource.groovy 中指定第二个数据源来连接到第二个数据库,例如:

dataSource_target {
dialect = org.hibernate.dialect.MySQLInnoDBDialect
pooled = true
jmxExport = true
driverClassName = "com.mysql.jdbc.Driver"
username = "bla"
password = "bla"
}

然后在控制器中,我们有

static mapping = {
    datasource 'ALL'
 }

那么在服务中,我们有:

         con = new Sql(dataSource_target)
         rows = con.rows(sql)

它有效,但有两个大问题:

  1. 如果在执行 grails run-app 时报告应用无法连接到第二个“目标”数据源,则它不会启动。

  2. 一旦运行,如果应用程序失去与目标数据库的连接,它不会尝试重新连接,您必须停止并重新启动整个 grails 应用程序。

我们需要更健壮的东西——目标数据库仅在用户决定运行报表时被调用——它不会在应用启动时运行,当我们调用 con = new Sql(datasource) 时应该尝试连接(或重新连接) )。

有什么想法可以实现这一目标吗? IE。一种在运行时连接到任意数据库的方法,拉回一些行,如果与目标数据库的连接丢失,然后重新建立,下次运行报告时它应该仍然有效。此外,如果应用程序在目标数据库不存在时启动,它仍然应该启动,因为它在启动时不依赖它。

谢谢,

【问题讨论】:

    标签: database grails datasource


    【解决方案1】:

    您可以考虑添加一些额外的属性以允许它尝试重新连接。例如:

    dataSource_target {
      dialect = org.hibernate.dialect.MySQLInnoDBDialect
      pooled = true
      jmxExport = true
      driverClassName = "com.mysql.jdbc.Driver"
      username = "bla"
      password = "bla"
      properties {
        maxActive = -1
        minEvictableIdleTimeMillis=1800000
        timeBetweenEvictionRunsMillis=1800000
        numTestsPerEvictionRun=3
        testOnBorrow=true
        testWhileIdle=true
        testOnReturn=true
        validationQuery="SELECT 1"
      }
    }
    

    我建议您更改属性以满足您的需要。但是,这并不能解决应用程序启动时数据库不可用的问题。

    为避免这种情况,您必须避免使用 Grails 数据源。在这种情况下,您需要在调用数据库的服务中定义数据源。

    def db = [
      url:'jdbc:hsqldb:mem:testDB', 
      user:'sa', 
      password:'', 
      driver:'org.hsqldb.jdbc.JDBCDriver'
    ]
    def sql = Sql.newInstance(db.url, db.user, db.password, db.driver)
    

    当然,修改它以满足您的需要。您甚至可以从 Config.groovy 中提取这些设置,而不是对其进行硬编码(强烈推荐)。

    【讨论】:

      【解决方案2】:

      要从 application.yml 动态获取这些值,我想这取决于 grails 3 的版本,因为我知道 dsn 的配置在 3.2.8 上略有变化:

      def db = [:]
      def dataSources = Holders.grailsApplication.config.dataSources
      db.user = dataSources.dataSource_otherDsn.username
      db.password = dataSources.dataSource_otherDsn.password
      db.driver = dataSources.dataSource_otherDsn.driverClassName
      if (Environment.current == Environment.DEVELOPMENT) {
          db.url = Holders.grailsApplication.config.environments.development.dataSources.dataSource_otherDsn.url
      } else if (Environment.current == Environment.PRODUCTION) {
          db.url = Holders.grailsApplication.config.environments.production.dataSource.dataSource_otherDsn.url
      
      }
      def sql = Sql.newInstance(db.url, db.user, db.password, db.driver)
      

      由于配置值被拆分到 .yml 文件的不同部分,我不得不在不同位置查找位。

      虽然这是在一项服务中,但使用标准 grailsApplication 的 GrailsApplicationAware 无法通过 Holders.grailsApplication 正常工作。虽然直接调用服务是BootStrap,所以可能与启动过程要求有关。

      不管怎样,这种方式会让它更有活力。

      【讨论】:

        猜你喜欢
        • 2018-09-07
        • 2023-03-10
        • 1970-01-01
        • 2021-12-27
        • 1970-01-01
        • 1970-01-01
        • 2013-10-08
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多