在liquibase开始工作之前,如何在Postgres DB中创建架构?

时间:2018-09-26 12:13:45

标签: java spring postgresql liquibase

我有独立的应用程序。它在Java,spring-boot,postgres上运行,并且具有liquibase。

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

application.properties:

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启动时,它将创建两个表databasechangelogs和另一个表。之后,liquibase开始工作。但是我想在liquibase.default-schema = my_schema中使用liquibase,但是当liquibase开始工作时它并不存在,并且它报错:异常是liquibase.exception.LockException:liquibase.exception.DatabaseException:错误:模式“ my_schema”不存在

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

liquibase.default-schema = my_schema

,但是在liquibase可以做到之前,必须先创建模式。 Liquibase无法执行此操作,因为它尚未启动,并且首先需要架构。 恶性循环。

2 个答案:

答案 0 :(得分:2)

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

org.springframework.jdbc.datasource.init.ScriptUtils在liquibase之前工作。

日志:

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 boot1.X。如果您使用的是Spring Boot 2,则应在属性文件中使用spring.datasource.initialization-mode=always启用schema.sql。 Spring Boot - Loading Initial Data

中的更多信息

答案 1 :(得分:0)

您可以为此使用 Spring Boot Pre-Liquibase module。这正是它的意义所在。它在执行 Liquibase 本身之前执行一些 SQL。 Pre-Liquibase 将自身设置在 Spring Boot AutoConfigure 链中,以确保它始终在 Liquibase 之前执行

步骤 1

将以下 Starter 添加到您的项目中:

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

步骤 2

src/main/resources/preliquibase 添加一个名为 postgresql.sql 的 SQL 文件,内容如下:

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

${} 语法表示占位符变量。 Pre-Liquibase 将从您的 Spring 环境中的属性解析它。

步骤 3

像这样设置应用程序属性:

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

现在 - 在本例中 - 唯一需要决定的是 my.db.schemaname 值的来源。那是你的选择。 example project 主张它应该来自操作系统环境变量,尤其是在您部署到云时。

最后的话

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

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