grails如何(重新)连接到第二个数据库

时间:2014-04-10 13:13:36

标签: database grails datasource

我们有一个grails应用程序,它有各种域对象存储在grails db中。该应用程序连接到第二个数据库,运行一些原始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应用程序。

  3. 我们需要更强大的东西 - 目标数据库仅在用户决定运行报告时调用 - 它在应用程序启动时不运行,并且当我们调用con = new Sql(数据源)时应尝试连接(或重新连接) )。

    我们如何实现这一目标? IE浏览器。一种在运行时连接到aribtrary数据库的方法,拉回一些行,如果与目标数据库的连接丢失,则重新建立,下次运行报表时它应该仍然有效。此外,如果应用程序在目标数据库不存在时启动,它仍应启动,因为它在启动时不依赖于它。

    谢谢,

2 个答案:

答案 0 :(得分:2)

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

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中提取这些设置,而不是对它们进行硬编码(强烈推荐)。

答案 1 :(得分:1)

要从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文件的不同段上分割的,我必须查找不同位置的位。

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

无论如何,它会以这种方式变得更有活力。