我们试图在grails2.5.3中实现基于模式的多租户,但是在hibernate(ver4.3.10)中遇到了一些问题。我们需要支持每请求租户切换,并且能够在应用程序运行时添加/删除租户(即数据源bean),而无需重新启动。
我们使用的abstractroutingdatasource与这里描述的类似:https://pritomkumar.blogspot.com/2014/10/grails-create-or-change-database.html
在resources.groovy中,以下代码创建switchabledatasource、root datasource,并为环境中定义的其他数据源创建bean:
parentDataSource(DriverManagerDataSource) { bean ->
bean.'abstract' = true
driverClassName = grailsApplication.config.dataSource.driverClassName
}
rootDataSource(DriverManagerDataSource) { bean ->
bean.parent = parentDataSource
bean.scope = 'prototype'
url = grailsApplication.config.dataSource.url
username = grailsApplication.config.dataSource.username
password = grailsApplication.config.dataSource.password
}
Map dataSourceMapping = [:]
dataSourceMapping[TenantManager.DATASOURCE_ADMIN] = ref('rootDataSource')
//Find all existing tenant datasources
Map tenantDataSources = grailsApplication.config.findAll {
it.key.toString().startsWith(TenantManager.DATASOURCE_TENANT_PREFIX)
}
tenantDataSources.each { String key, ConfigObject dataSource ->
"$key"(DriverManagerDataSource) { bean ->
bean.parent = parentDataSource
bean.scope = 'prototype'
url = dataSource.url
username = dataSource.username
password = dataSource.password
}
dataSourceMapping[key] = ref("$key")
}
dataSource(SwitchableDataSource) {
targetDataSources = dataSourceMapping
}
我们有一个rest服务,它允许我们提供一个新的租户数据源,它使用类似的代码:
private Map registerDataSourceBean(Tenant tenant) {
Map dataSourceParams
ApplicationContext ctx = grailsApplication.mainContext
String dataSourceName = TenantManager.getDataSourceNameForTenant(tenant.tenantId)
if (!ctx.containsBean(dataSourceName)) {
String dataSourceUser = DB_PREFIX + tenant.tenantId
BeanBuilder bb = new BeanBuilder()
bb.beans {
"$dataSourceName"(DriverManagerDataSource) { bean ->
bean.parent = ref('parentDataSource')
bean.scope = 'prototype'
url = tenant.dataSourceUrl
username = dataSourceUser
password = dataSourceUser
}
}
bb.registerBeans(ctx)
dataSourceParams = [:]
dataSourceParams['username'] = dataSourceUser
dataSourceParams['url'] = tenant.dataSourceUrl
dataSourceParams['dataSourceName'] = dataSourceName
log.info("Created datasource [$dataSourceName]")
} else {
log.error("Datasource bean [$dataSourceName] already exists")
}
dataSourceParams
}
作为这个过程的一部分,我们随后将数据源写入配置文件。在大多数情况下,这种模式是有效的,但我们看到了一些问题。
在运行时创建的数据源的连接方式似乎与在resources.groovy中创建的数据源不同。具体来说,运行时数据源在grailsapplication.maincontext.eventtriggeringinterceptor.datastores中没有hibernatedatastore,而在resources.groovy中没有。这限制了为租户创建持久性事件侦听器的能力,因为我们没有对该实体的引用(我不知道如何创建一个持久性事件侦听器)。这通常让我担心这个运行时DriverManager数据源没有正确使用hibernate。
也许我在这个过程中遗漏了一些步骤来正确地连接数据源以供使用。
如果有人知道我可能错过了什么,或者是谁在我之前走过这条路,我将非常感谢任何帮助。感谢您的光临!
暂无答案!
目前还没有任何答案,快来回答吧!