using spring boot profiles with liquibase changeset context attribute to manage changset scope - postgresql

I am trying to do a proof of concept application with spring boot and liquibase. I basically want to create a spring boot app that can manage liquibase changesets by utilizing the changeset attribute called context, so that changesets with no context can be applied to any spring boot profile, whereas changesets with specific context (e.g context="dev" ) will only be applied if spring boot profiles of that type, is active (e.g spring.profiles.active=dev).
In my app, i have the following spring profiles -> dev, prod (each specified correctly in the application yaml file with the relavant profile db credentials also specified under the profile). What do I need to do to make this work. below is my application.yaml
spring:
application:
name: liquibase-spring-jpa-postgres-example
liquibase:
change-log: db.changelog/db.changelog-master.xml
spring:
profiles: dev
datasource:
url: jdbc:postgresql://localhost:5432/dev
username: postgres
password: password
driver-class-name: org.postgresql.Driver
spring:
profiles: ci
datasource:
url: jdbc:postgresql://localhost:5432/ci
username: postgres
password: password
driver-class-name: org.postgresql.Driver
spring:
profiles: qa
datasource:
url: jdbc:postgresql://localhost:5432/qa
username: postgres
password: password
driver-class-name: org.postgresql.Driver
spring:
profiles: production
datasource:
url: jdbc:postgresql://localhost:5432/prod
username: postgres
password: password
driver-class-name: org.postgresql.Driver
and below is the current databaseChangeLog file (the second change set shouldn't run if my spring profile is prod).
<changeSet id="20161016_my_first_change" author="fike" context="dev, qa, ci, production">
<sql>
CREATE TABLE customer
(
id BIGSERIAL PRIMARY KEY,
firstname character varying NOT NULL,
lastname character varying NOT NULL
);
</sql>
<rollback>
drop table customer;
</rollback>
</changeSet>
<changeSet id="20161016_my_first_change2" author="krudland" context="dev">
<sql>
insert into customer (firstname, lastname) values ('Franklin','Ike');
</sql>
<rollback>
delete from customer where firstname = 'Franklin' and lastname = 'Ike';
</rollback>
</changeSet>
I basically need to be able to manage my liquibase context, using my spring profile. Is this possible?

You need to define 'liquibase.contexts' property into your yaml file. Something like below.
spring:
profiles: dev
datasource:
url: jdbc:postgresql://localhost:5432/dev
username: postgres
password: password
driver-class-name: org.postgresql.Driver
liquibase:
contexts: dev
After adding this the below change set will only execute when your local profile is 'dev' (i.e. spring-boot:run -Dspring.profiles.active=dev)
<changeSet id="20161016_my_first_change2" author="krudland" context="dev">
<sql>
insert into customer (firstname, lastname) values ('Franklin','Ike');
</sql>
<rollback>
delete from customer where firstname = 'Franklin' and lastname = 'Ike';
</rollback>
</changeSet>

The better way is to reference spring profile in liquibase context settings, starting from spring boot version 2 only thing you need to add to main application.yml or application.properties is:
spring.liquibase.contexts=${spring.profiles.active}
Your active spring profile will be used as active liquibase context.

Related

Unable to connect to the database. Configure the url, user and password

I have a spring boot app and I need flyway migration. After I configured in application.yml like this:
flyway:
driverClassName: org.postgresql.Driver
locations: classpath:src/main/resources/db/migration
url: jdbc:postgresql://localhost:5432/myDB
user: postgres
password: 123
schemas: public
enable: true
baseline-on-migrate: true
I got an error when tried to use flyway:migrate or flyway:repair: Unable to connect to the database. Configure the url, user and password!
What I'm doing wrong?!

liquibase default schema ignored in sql changelog

Problem: liquibase can't find table without setting schema in SQL script.
How to say liquibase use default schema in SQL changelog?
Before sql changelog, for adding check constraint, I create all table, without setting schema. Schema was set in application.properties and all table was created correctly in $RM_DB_SCHEMA.
RM_DB_SCHEMA: MANAGER
RM_DB_URL: "jdbc:h2:file:~/rmdb;MODE=PostgreSQL;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE;AUTO_SERVER=TRUE;INIT=CREATE SCHEMA IF NOT EXISTS ${RM_DB_SCHEMA}"
RM_DB_USER: sa
RM_DB_PASSWORD: admin
RM_LB_USER: ${RM_DB_USER}
RM_LB_PASSWORD: ${RM_DB_PASSWORD}
spring:
datasource:
hikari:
schema: ${RM_DB_SCHEMA}
username: ${RM_DB_USER}
password: ${RM_DB_PASSWORD}
jdbc-url: ${RM_DB_URL}
liquibase:
change-log: "classpath:db/manager-changelog.xml"
default-schema: ${RM_DB_SCHEMA}
user: ${RM_LB_USER}
password: ${RM_LB_PASSWORD}
jpa:
database: postgresql
Caused by: liquibase.exception.LiquibaseException: liquibase.exception.MigrationFailedException: Migration failed for change set changelog.xml::d::d:
Reason: liquibase.exception.DatabaseException: Таблица "STATUS" не найдена
Table "STATUS" not found; SQL statement:
ALTER TABLE TEST ADD CONSTRAINT STATUS_ID CHECK (exists (SELECT 1 FROM STATUS s WHERE STATUS_ID = s.id)) [42102-200] [Failed SQL: (42102) ALTER TABLE TEST ADD CONSTRAINT STATUS_ID CHECK (exists (SELECT 1 FROM STATUS s WHERE STATUS_ID = s.id))]
I found another solution.
The problem was in local developing with h2. (it always init as public schema). I'm just adding SET SCHEMA after creating it.
in test properties:
jdbc-url: 'jdbc:h2:file:~/rmdb;MODE=PostgreSQL;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE;AUTO_SERVER=TRUE;INIT=CREATE SCHEMA IF NOT EXISTS ${application.database.schema}\;SET SCHEMA ${application.database.schema}'

How can I connect to an h2 database via odbc / postgres driver where one table contains blob fields?

I'm trying to access an h2 database via odbc. The database itself is running with h2 in server mode. Later on, I try to create an odbc datasource with the postgres unicode sql driver (psqlodbc). If I test my connection with a valid username an password, the h2 console reports an exception and the server process is killed.
Is there another way or parameter to allow the connection via odbc? I tried to append ;MODE=PostgreSQL to the database name but it didn't help.
The following exception is shown (field names and ip addresses removed):
CP server running at tcp://...:9092 (only local connections)
PG server running at pg://...:5435 (only local connections)
Web Console server running at http://...:8082 (only local connections)
org.h2.jdbc.JdbcSQLNonTransientException: Unbekannter Datentyp: "BLOB"
Unknown data type: "BLOB"; SQL statement:
CREATE CACHED TABLE "..."."...."(
"ID" VARCHAR(40) NOT NULL, ..
"SOME_DATA" BLOB, ...
) [50004-200]
at org.h2.message.DbException.getJdbcSQLException(DbException.java:505)
at org.h2.message.DbException.getJdbcSQLException(DbException.java:429)
at org.h2.message.DbException.get(DbException.java:205)
at org.h2.message.DbException.get(DbException.java:181)
at org.h2.command.Parser.parseColumnWithType(Parser.java:5971)
at org.h2.command.Parser.parseColumnForTable(Parser.java:5697)
at org.h2.command.Parser.parseTableColumnDefinition(Parser.java:8442)
at org.h2.command.Parser.parseCreateTable(Parser.java:8379)
at org.h2.command.Parser.parseCreate(Parser.java:6276)
at org.h2.command.Parser.parsePrepared(Parser.java:903)
at org.h2.command.Parser.parse(Parser.java:843)
at org.h2.command.Parser.parse(Parser.java:815)
at org.h2.command.Parser.prepare(Parser.java:722)
at org.h2.engine.Session.prepare(Session.java:622)
at org.h2.engine.Session.prepare(Session.java:606)
at org.h2.engine.MetaRecord.execute(MetaRecord.java:58)
at org.h2.engine.Database.open(Database.java:759)
at org.h2.engine.Database.openDatabase(Database.java:307)
at org.h2.engine.Database.<init>(Database.java:301)
at org.h2.engine.Engine.openSession(Engine.java:74)
at org.h2.engine.Engine.openSession(Engine.java:192)
at org.h2.engine.Engine.createSessionAndValidate(Engine.java:171)
at org.h2.engine.Engine.createSession(Engine.java:166)
at org.h2.engine.Engine.createSession(Engine.java:29)
at org.h2.engine.SessionRemote.connectEmbeddedOrServer(SessionRemote.java:340)
at org.h2.jdbc.JdbcConnection.<init>(JdbcConnection.java:173)
at org.h2.server.pg.PgServerThread.process(PgServerThread.java:235)
at org.h2.server.pg.PgServerThread.run(PgServerThread.java:101)
at java.lang.Thread.run(Unknown Source)
I experienced the same problem.
I had a test application properties with wrong dialect:
spring:
jpa:
database-platform: org.hibernate.dialect.H2Dialect
open-in-view: false
hibernate:
ddl-auto: create-drop
naming:
physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
implicit-strategy: org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyJpaImpl
properties:
hibernate:
dialect: org.hibernate.dialect.H2Dialect
default_schema: schema
I changed in this way. Everything is working fine.
spring:
jpa:
database-platform: org.hibernate.dialect.PostgreSQL10Dialect
open-in-view: false
hibernate:
ddl-auto: create-drop
naming:
physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
implicit-strategy: org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyJpaImpl
properties:
hibernate:
dialect: org.hibernate.dialect.PostgreSQL10Dialect
default_schema: schema
To check database version I used:
select version();

Spring Boot + PostgreSQL: cannot find schema to create Camunda tables

I am trying to create tables for camunda (7.14.0) at Spring Boot application start. I have manually created a PostgreSQL schema in advance with the name "camunda". When I run the Spring Boot application, it gives me an error:
ENGINE-03017 Could not perform operation 'create' on database schema for SQL Statement ...
and
org.postgresql.util.psqlexception: no schema has been selected to create in
My application.yml config:
camunda:
bpm:
database:
type: postgres
schema-update: create
schema-name: camunda
username: camunda
password: camunda
table-prefix: camunda.
How can I create camunda tables in a schema with a specific name?
Example config:
spring.datasource:
url: jdbc:postgresql://localhost:5432/postgres?autoReconnect=true
username: cam1
password: cam1
driver-class-name: org.postgresql.Driver
camunda:
bpm:
database:
schema-name: cam1
table-prefix: cam1.
Ensure the schema has been created and user used has been given the permissions on the target schema.
Full example for two Camunda instances using separate schemas: https://github.com/rob2universe/two-camunda-instances

Spring Boot JPA Schema Initialization

I want to initialise my datasource with a DLL script in my spring boot project (only during dev of course). As mentioned in the docs here I set the spring.datasource.schema property to the DLL scripts which is in src/main/resources/postgresql/define-schema.sql.
spring:
profiles: dev
datasource:
platform: postgresql
driver-class-name: org.postgresql.Driver
url: jdbc:postgresql://localhost:5432/postgres
username: postgres
password: ****
initialize: true
schema: ./postgresql/define-schema.sql
continue-on-error: false
jpa:
hibernate:
ddl-auto: validate
generate-ddl: false
show-sql: true
But the script won't be executed. I also tried to put it on the class path root and call it schema.sql ... Nothing happens.
The dev profile is selected, at least I see it in the log: The following profiles are active: dev
The application than fails on the JPA schema validation.
The only warning I get from hibernate:
Found use of deprecated [org.hibernate.id.SequenceGenerator] sequence-based id generator; use org.hibernate.id.enhanced.SequenceStyleGenerator instead. See Hibernate Domain Model Mapping Guide for details.
But I don't think this has any to do with the initialise problem.
I've got spring-boot-security-starter in my dependencies but not configured yet, could that be a problem source?
Does anybody recognise an obivous typo, mistake anything else?
Looking forward hearing from you!
Amp
Prefix the path to your sql script with classpath
Example:
spring.datasource.schema=classpath:/postgresql/define-schema.sql