如何在Postgres DB中创建架构,然后再开始工作?

2022-09-03 14:54:56

我有独立的应用程序。它在java,spring-boot,postgres上,它有liquibase。

我需要部署我的应用程序,liquibase应该创建所有表,等等。但它应该在自定义架构中执行此操作,而不是在公共架构中。liquibase 的所有服务表(数据库更改日志和数据库更改日志锁)也应该在自定义架构中。如何在 liquibase 开始工作之前在 DB 中创建我的架构?我必须在我的应用程序中进行部署,在配置或类似内容中执行此操作。无需对数据库进行任何手动干预。

应用程序.属性:

spring.datasource.jndi-name=java:/PostgresDS
spring.jpa.properties.hibernate.default_schema=my_schema
spring.jpa.show-sql = false
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect
spring.datasource.continue-on-error=true
spring.datasource.sql-script-encoding=UTF-8

liquibase.change-log = classpath:liquibase/changelog-master.yaml
liquibase.default-schema = my_schema

UPD:

当 liquibase 开始时,它会创建两个表数据库更改日志和另一个表。之后,液化物开始工作。但是我想要 liquibase in ,但是当 liquibase 开始工作时它不存在,这是一个错误:exception 是 liquibase.exception.LockException: liquibase.exception.DatabaseException: ERROR: schema “my_schema” 不存在liquibase.default-schema = my_schema

我希望在自定义架构中进行 liquibase 工作,而不是在公共环境中工作:

liquibase.default-schema = my_schema

但是在 liquibase 可以做到这一点之前,必须创建架构。Liquibase不能这样做,因为它还没有启动,对于启动,它需要模式。恶性循环。


答案 1

我用我的 application.properties 找到了一个解决方案。

org.springframework.jdbc.datasource.init.ScriptUtils在液化基之前工作过。

原木:

14:11:14,760 INFO  [org.springframework.jdbc.datasource.init.ScriptUtils] 
(ServerService Thread Pool -- 300) Executing SQL script from URL 
[vfs:/content/app.war/WEB-INF/classes/schema.sql]

14:11:14,761 INFO  [org.springframework.jdbc.datasource.init.ScriptUtils] 
(ServerService Thread Pool -- 300) Executed SQL script from URL 
[vfs:/content/app.war/WEB-INF/classes/schema.sql] in 1 ms.

14:11:14,912 ERROR [stderr] (ServerService Thread Pool -- 300) INFO 9/27/18 
2:11 PM: liquibase: Successfully acquired change log lock

14:11:15,292 ERROR [stderr] (ServerService Thread Pool -- 300) INFO 9/27/18 
2:11 PM: liquibase: Reading from my_schema.databasechangelog

14:11:15,320 ERROR [stderr] (ServerService Thread Pool -- 300) INFO 9/27/18 
2:11 PM: liquibase: Successfully released change log lock

我只是投入资源目录,一切正常。schema.sqlCREATE SCHEMA IF NOT EXISTS my_schema;

谢谢大家的帮助。

更新:这是Spring boot 1.X的工作。如果您使用的是 Spring Boot 2,则应在属性文件中启用 schema.sql,并使用 .更多信息 Spring Boot - 加载初始数据spring.datasource.initialization-mode=always

更新2:在Spring Boot 2.5.2中(可能在早期版本中也是如此),正如@peterh在评论中所写的那样,此解决方案现在不起作用。可悲但真实。我尝试这个解决方案的最后一个版本,它的工作是Spring Boot 2.0.9在文档中Spring Boot说它是从Spring Boot 2.5.x重新设计的

更新3:一些信息为什么他们杀死这个功能 - >https://github.com/spring-projects/spring-boot/issues/22741


答案 2

您可以使用Spring Boot Pre-Liquibase模块来实现此目的。这正是它的本意。它在执行 Liquibase 本身之前执行一些 SQL。Pre-Liquibase在Spring Boot AutoConfigure链中设置自己,以便保证它始终在Liquibase之前执行。

步骤1

将以下初学者添加到项目中:

<dependency>
    <groupId>net.lbruun.springboot</groupId>
    <artifactId>preliquibase-spring-boot-starter</artifactId>
    <version>  ---latest-version---  </version>
</dependency>

第 2 步

添加一个 SQL 文件,其名称和内容如下所示:src/main/resources/preliquibasepostgresql.sql

CREATE SCHEMA IF NOT EXISTS ${spring.liquibase.default-schema};

语法表示占位符变量。预液化碱将从春季环境中的属性中解析它。${}

第 3 步

按如下方式设置应用程序属性:

spring.liquibase.default-schema=${my.db.schemaname}
spring.jpa.properties.hibernate.default_schema=${my.db.schemaname}

现在 - 在这个例子中 - 唯一需要决定的是值来自哪里。这是你的选择。示例项目主张它应该来自操作系统环境变量,特别是如果您要部署到云中。my.db.schemaname

结语

警告:Pre-Liquibase可能过于灵活,因为它允许执行任何SQL代码。不要试图把东西放在预 Liquibase 文件中,这些文件理应属于 Liquibase ChangeSet。老实说,我能想到的Pre-Liquibase的唯一用法是设置一个数据库“home”(意思是模式或目录),Liquibase db对象可以位于其中,以便同一应用程序的实例可以按模式或目录分隔,同时驻留在同一数据库服务器上。

(披露:我是Pre-Liquibase模块的作者)


推荐