spring - 无法在 Grails 3 中动态配置支持 GORM 的数据源

标签 spring grails grails-orm

我们正在实现一个 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/

相关文章:

java - 如何获取 Spring Boot 和 OAuth2 示例以使用默认密码授予凭据以外的其他凭据

sql - 在gral HQL中,我将如何使用(非聚合的)Oracle函数?

ruby-on-rails - 读取Heroku日志的更好方法

unit-testing - 在 Grails 2.2 中是否可以对 mongodb 动态属性进行单元测试?

Grails 命名查询不适用于 "in"语句

java - JPA 仅创建一次查询

java - ajax GET请求Spring的403禁止错误

Grails 验证错误从服务到 Controller 消失

java - Hibernate 和映射到单个表的两个类

公开为 REST 服务的 Grails 服务方法