我们有一个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)
它有效,但有两大问题:
如果报告应用无法连接到第二个"目标"当你做grails run-app时,数据源就不会启动了。
一旦运行,如果应用程序失去与目标数据库的连接,它将不会尝试重新连接,您必须再次停止并启动整个grails应用程序。
我们需要更强大的东西 - 目标数据库仅在用户决定运行报告时调用 - 它在应用程序启动时不运行,并且当我们调用con = new Sql(数据源)时应尝试连接(或重新连接) )。
我们如何实现这一目标? IE浏览器。一种在运行时连接到aribtrary数据库的方法,拉回一些行,如果与目标数据库的连接丢失,则重新建立,下次运行报表时它应该仍然有效。此外,如果应用程序在目标数据库不存在时启动,它仍应启动,因为它在启动时不依赖于它。
谢谢,
答案 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,但可能与启动流程要求有关。
无论如何,它会以这种方式变得更有活力。