Issue
I have standalone application. It’s on java, spring-boot, postgres and it has liquibase.
I need to deploy my app and liquibase should create all tables, etc. But it should do it into custom schema not in public. All service tables of liquibase (databasechangelog and databasechangeloglock) should be in custom schema too. How can I create my schema in DB before liquibase start to work? I must do it inside my app when it’s deploying, in config or some like. Without any manual intervention into the DB.
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:
When liquibase start, it's create two tables databasechangelogs and one more table. After that, liquibase start working. But I want liquibase in liquibase.default-schema = my_schema
, but it's not exist when liquibase start to work and it an error: exception is liquibase.exception.LockException: liquibase.exception.DatabaseException: ERROR: schema "my_schema" does not exist
I want liquibase work in custom schema, not in public:
liquibase.default-schema = my_schema
but before liquibase can do it, the schema must be created. Liquibase can't do this because it not started yet and for start it needs schema. Vicious circle.
Solution
I found a solution with my application.properties.
org.springframework.jdbc.datasource.init.ScriptUtils
worked before liquibase.
Logs:
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
I just put schema.sql
with CREATE SCHEMA IF NOT EXISTS my_schema;
into resources dir and all working properly.
Thanks all for help.
Update: It's work for Spring boot 1.X. If you are use Spring Boot 2, you should enable schema.sql in properties file, with spring.datasource.initialization-mode=always
.
More info in Spring Boot - Loading Initial Data
Update 2: In Spring Boot 2.5.2 (maybe in earlier versions too) this solution is not working now, as @peterh has wrote in comment. Sad but true. The last version I was try this solution and it's work was Spring Boot 2.0.9 In docs Spring Boot says that it was redesigned from Spring Boot 2.5.x
Update 3: Some information why they kill this feature -> https://github.com/spring-projects/spring-boot/issues/22741
Answered By - G.O.
Answer Checked By - Mary Flores (JavaFixing Volunteer)