如何让 Spring Boot 使用 MultiTenantSpringLiquibase?

Posted

技术标签:

【中文标题】如何让 Spring Boot 使用 MultiTenantSpringLiquibase?【英文标题】:How to make Spring Boot use MultiTenantSpringLiquibase? 【发布时间】:2019-02-15 22:58:33 【问题描述】:

在我的 Spring Boot 应用程序中,我希望 Liquibase 在 PostgreSQL 数据库上创建表,因此在我的配置类中,我设置了一个返回 MultiTenantSpringLiquibase 的 Bean,其中包含它应该使用的架构名称。

问题是这个 Bean 被创建但被忽略了,Spring Boot 在 LiquibaseAutoConfiguration 中找到一个有效的 SpringLiquibase Bean,并在我的数据库上使用它,访问我打算用于 MultiTenantSpringLiquibase 的相同更改日志。这失败了,因为此配置尝试使用不存在的模式“public”。如果确实存在,它会创建我在更改日志中定义的表,但我不希望它们出现在“公共”架构中。

如何防止 LiquibaseAutoConfiguration 或 SpringLiquibase 执行,以便使用我的 MultiTenantSpringLiquibase Bean?

【问题讨论】:

我上个月做了这个,但我现在在家。星期一在这里不好回答。 试试这个代码示例:gist.github.com/cavarzan/3134363a293f18fbe4cddce208e7df29 您可以跳过默认架构,只在其他架构中执行迁移。如果作品我作为答案发布 你能提供给我们你的 MultiTenantSpringLiquibase 的 bean 定义吗?由于这个类实现了 InitializingBean 接口,Spring 应该在将 bean 添加到应用程序上下文之后立即调用 afterPropertiesSet 方法。当您在此方法中设置调试器断点时会发生什么? 【参考方案1】:

您应该至少有SpringLiquibase bean 作为默认模式。 在这种情况下,您可以跳过此 bean 的执行,但需要声明它。

@Bean
public SpringLiquibase liquibase(@Qualifier("taskExecutor") TaskExecutor taskExecutor,
                                     DataSource dataSource, LiquibaseProperties liquibaseProperties) 
     SpringLiquibase liquibase = new AsyncSpringLiquibase(taskExecutor, env);
     liquibase.setDataSource(dataSource);
     liquibase.setChangeLog("path-to-xml");
     liquibase.setContexts(liquibaseProperties.getContexts());
     liquibase.setDefaultSchema(liquibaseProperties.getDefaultSchema());
    return liquibase;

完成此配置后,您应该能够创建MultiTenantSpringLiquibase Bean 以在所有模式中运行:

@Bean
@DependsOn("liquibase") // ensure execution after SpringLiquibase Bean
public MultiTenantSpringLiquibase liquibaseMt(DataSource dataSource, LiquibaseProperties liquibaseProperties) 

    MultiTenantSpringLiquibase liquibase = new MultiTenantSpringLiquibase();

    liquibase.setDataSource(dataSource);
    liquibase.setChangeLog("path-to-xml");
    liquibase.setDefaultSchema(YOUR_DEFAULT_SCHEMA);
    liquibase.setSchemas(YOUR_ARRAY_OF_SCHEMAS);
    return liquibase;

SpringLiquibase 执行后,MultiTenantSpringLiquibase 将在您的架构中由liquibase.setSchemas(...) 行调用和执行

这个示例是我最近使用的一个工作示例。

完整示例类here。

【讨论】:

这是一个有效的答案,我可以使用“shouldRun=false”设置一个 SpringLiquibase Bean,但在我的情况下,由于我根本不使用默认模式,我更喜欢使用Jade Devin Nocum Cabatlao 的解决方案,它更准确地回答了我的具体问题(让 Spring Boot 仅使用 MultiTenantSpringLiquibase 并避免在默认模式上运行任何东西)。感谢您让我了解这是如何工作的。 当然!事实上,我也从我的 App 类中排除了 de LiquebaseAutoConfig!让我们保留这个可能对其他人有帮助的答案。 无法正常工作:总是在创建的第一个架构上出现错误。错误:tenant1.tablename 的表已经存在...我正在尝试制作 Jhipster 多租户应用程序【参考方案2】:

在你的 application.properties 中,添加这个。

spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration 

或者在你的 Main 类中使用这个。

@SpringBootApplication(exclude=LiquibaseAutoConfiguration.class)

【讨论】:

正是我想要的!我想知道为什么这么难找到,可能是因为 MultiTenantSpringLiquibase 和 Spring Boot 的组合,以及只使用没有“通用”模式的多租户的特殊需要。【参考方案3】:

您是否尝试将其添加到您的 application.properties 文件中:

#Disable Liquibase
spring.liquibase.enabled=false

如果你不禁用它,我相信这会被执行:

https://github.com/spring-projects/spring-boot/blob/master/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/liquibase/LiquibaseAutoConfiguration.java#L74

这只是一个想法,我不确定,但你可以尝试,因为你有环境,我只能推测。

【讨论】:

我试了几次,这个属性确实阻止了不需要的 SpringLiquibase 被执行,但是我的 MultiTenantSpringLiquibase 似乎也被这个禁用了。我试图了解在数据库上“执行”所选 Liquibase 配置的机制,因为我不确定我是否正确假设我的表应该在没有额外配置的情况下创建。当我有更多细节时,我会添加细节。也许需要一个 MWE,但在这种情况下,它需要 Spring Boot、一个数据库和一个使用 MultiTenantSpringLiquibase 的配置类。

以上是关于如何让 Spring Boot 使用 MultiTenantSpringLiquibase?的主要内容,如果未能解决你的问题,请参考以下文章

如何让 Spring Boot 应用程序在 tomcat 失败时退出

如何让 spring boot cloud/actuator 支持 prometheus Exemplars?

如何让 Spring Boot Actuator LdapHealthIndicator 与 Spring Security 的 Ldap 一起运行?

如何让我的 Spring Boot 应用程序使用给定的用户名和密码登录到 keycloak?

如何让 Linkedin OAuth 在 Spring Boot 中工作

如何让IDEA像STS那样高效调试Spring Boot程序