我们正在实现一个 Multi-Tenancy 应用程序(每个租户的数据库),并希望在不重新启动服务器的情况下动态配置新租户。这是 Grails 3.2.9/GORM 6。
其中包括在运行时创建一个数据源,而无需在 application.yml
中进行配置。在应用程序启动时。
根据the documentation (11.2.5. Adding Tenants at Runtime)存在用于在运行时添加租户的 ConnectionSources API,但是以这种方式创建的 ConnectionSource 似乎没有在 Spring 中正确注册(数据源、 session 和事务管理器的 bean),当我们尝试使用新的时,Grails 提示缺少 bean数据源。
我们希望当我们使用 ConnectionSources API 为新数据库创建连接源时,Grails 应该根据我们应用程序中的 GORM Domains 使用所有表对其进行初始化,执行 Bootstrap.groovy 等,就像它为application.yml
中静态配置的源不过,这也没有发生。
所以我的问题是 ConnectionSources API 的目的是否与我们尝试使用它的目的不同,或者它还没有完成/测试。
最佳答案
我是想回到你身边。我确实设法找到了解决方案。现在这是针对每个客户的架构,而不是每个客户的数据库,但我怀疑它很容易适应。我首先使用直接的 Groovy Sql 对象创建模式,如下所示:
void createAccountSchema(String tenantId) {
Sql sql = null
try {
sql = new Sql(dataSource as DataSource)
sql.withTransaction {
sql.execute("create schema ${tenantId}" as String)
}
} catch (Exception e) {
log.error("Unable to create schema for tenant $tenantId", e)
throw e
} finally {
sql?.close()
}
}
然后我运行与 Liquibase 插件相同的代码,并使用一些简单的默认值,如下所示:
void updateAccountSchema(String tenantId) {
def applicationContext = Holders.applicationContext
// Now try create the tables for the schema
try {
GrailsLiquibase gl = new GrailsLiquibase(applicationContext)
gl.dataSource = applicationContext.getBean("dataSource", DataSource)
gl.dropFirst = false
gl.changeLog = 'changelog-m.groovy'
gl.contexts = []
gl.labels = []
gl.defaultSchema = tenantId
gl.databaseChangeLogTableName = defaultChangelogTableName
gl.databaseChangeLogLockTableName = defaultChangelogLockTableName
gl.afterPropertiesSet() // this runs the update command
} catch (Exception e) {
log.error("Exception trying to create new account schema tables for $tenantId", e)
throw e
}
}
最后,我将新模式告诉 Hibernate,如下所示:
try {
hibernateDatastore.addTenantForSchema(tenantId)
} catch (Exception e) {
log.error("Exception adding tenant schema for ${tenantId}", e)
throw e
}
在任何你看到我提到“hibernateDatastore”或“dataSource”的地方,我都有 Grails 注入(inject)的内容,如下所示:
def hibernateDatastore
def dataSource
protected String defaultChangelogTableName = "databasechangelog"
protected String defaultChangelogLockTableName = "databasechangeloglock"
希望这可以帮助。
关于spring - 无法在 Grails 3 中动态配置支持 GORM 的数据源,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44176219/