Spring Boot JPA Schema Initialization - postgresql

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

Related

Not able to set keepAliveTime config for Hikari in SpringBoot

I have an spring-boot based application that connects to postgres DB. It uses the default HikariCP as JDBC connection pool. From the documentation I see that we can configure a property keepALiveTime which I think is useful to us but I am not able to set it in my yml file. It looks like this
datasource:
jdbc-url: jdbc:postgresql://x.x.x.x:5433/xxx?sslmode=require&sslcert=/file.crt&sslkey=/tmp/file.key
username: ${JDBC_USERNAME}
password: ${JDBC_PASSWORD}
keepaliveTime: 80000
jpa:
hibernate:
ddl-auto: update
show-sql: true
properties:
hibernate.format_sql: true
hibernate.dialect: org.hibernate.dialect.PostgreSQL81Dialect
hikari:
idle-timeout: 500000
minimum-idle: 10
maximum-pool-size: 15
keepaliveTime: 80000
max-lifetime: 48000
connection-timeout: 180000
All other configs are auto suggested and are able to be used. But keepAliveTime option is not available for me to populate. Although I am providing it in the configs Hikari doesn't use it.
keepAliveTime parameter arrived in HikariCP 4.0.0. In order to use it with older version of spring boot - we can exclude the HikariCP dependency from where it is being read and explicitly the version that we want. Its not recommended but I found no issues using 4.0.0 version with spring boot version 2.3.0-Release
To remove the dependency
implementation('org.springframework.boot:spring-boot-starter-data-jpa') {
exclude group: 'com.zaxxer', module: 'HikariCP'
}
To add the dependency
implementation('com.zaxxer:HikariCP:4.0.3') {
force=true
}
I added the keepAliveTime in DataSource Configuration file
public HikariDataSource dataSource() {
HikariDataSource h = DataSourceBuilder.create().type(HikariDataSource.class).build();
System.out.println(h.getJdbcUrl());
h.setKeepaliveTime(100000l);
h.setJdbcUrl("yufuyfuyfu");
System.out.println(h.getJdbcUrl());
return h;
}
please notice that keepAliveTime should be less than maxLifeTime, from HikariCP docs:
This property controls how frequently HikariCP will attempt to keep a connection alive, in order to prevent it from being timed out by the database or network infrastructure. This value must be less than the maxLifetime value

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();

SequenceInformation missing

I'm working with a Spring boot Application connecting to an AS400 Database using the com.ibm.db2.jcc.DB2Driver driver with Spring Data JPA.
I use the org.hibernate.dialect.DB2Dialect dialect.
When I start the Application, I get the Error
Could not fetch the SequenceInformation from the database
com.ibm.db2.jcc.am.SqlSyntaxErrorException: DB2 SQL Error: SQLCODE=-204, SQLSTATE=42704, SQLERRMC=SYSCAT.SEQUENCES;TABLE, DRIVER=4.26.14
Meaning the Table SYSCAT.SEQUENCES is missing, which it is, because it's not needed.
The Application works fine, but the error bothers me.
As far as I see, SequenceInformations are only important when I generate an ID somewhere, what I don't do.
This Application is only used to copy data from one place to another, so I only use JPAs #Id annotation but not the #GeneratedValue one.
Am I missing some use for the SequenceInformation?
Is there some way to turn off the fetching of SequenceInformation?
Those are my application properties:
spring:
datasource:
driver-class-name: com.ibm.db2.jcc.DB2Driver
hikari.connection-test-query: values 1
hikari.maximum-pool-size: 25
jpa:
database-platform: DB2Platform
hibernate.ddl-auto: none
open-in-view: false
properties:
hibernate:
dll-auto: none
dialect: org.hibernate.dialect.DB2Dialect
naming-strategy: org.hibernate.cfg.ImprovedNamingStrategy
You use the wrong dialect. Please use:
org.hibernate.dialect.DB2400Dialect
I have changed dialect from DB2Dialect to DB2400Dialect and it worked for me.
##spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.DB2Dialect
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.DB2400Dialect

Liquibase diff - Driver issue

i tried to make a
liquibase xml with liquibase diff
command.
I want to do this based on this documentation: http://www.liquibase.org/documentation/diff.html
If I try to exec the example command with my custom properties,
with
--driver:org.postgresql.Driver,
I got this problem:
"Unexpected error running Liquibase: java.lang.RuntimeException:
Cannot find database driver: org.postgresql.Driver"
You have to specify the classpath where the driver jar file is located using the classpath key (liquibase documentation).
Your properties file should look like:
driver: org.postgresql.Driver
classpath: postgresql-driver.jar
url: jdbc:postgres#localhost:5432
username: scott
password: tiger

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

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.