I'm actually writing a small web application with spring boot and wanted to use a (embedded) H2 database together with Spring Data JPA and Flyway for database migration.
This is my application.properties:
spring.datasource.url=jdbc:h2:~/database;DB_CLOSE_ON_EXIT=FALSE;DB_CLOSE_DELAY=-1;
spring.datasource.username=admin
spring.datasource.password=admin
spring.datasource.driver-class-name=org.h2.Driver
In the main() method of my #SpringBootApplication class I do the following:
ResourceBundle applicationProperties = ResourceBundle.getBundle("application");
Flyway flyway = new Flyway();
flyway.setDataSource(applicationProperties.getString("spring.datasource.url"), applicationProperties.getString("spring.datasource.username"), applicationProperties.getString("spring.datasource.password"));
flyway.migrate();
I added a script, which creates a table USER in the database, Flyway says it is correctly migrated, but if I connect to the database, in schema PUBLIC theres only the schema_versions table of Flyway listed.
If I am adding another script, which inserts base data into the USER table, the migration failes, because the table is not present after a restart of my spring boot application.
Can anyone tell me if there is missing in my configuration? Or if there is any wrong assumption in my setup...
I have not enough data about your configuration
Hint:
See migration file must be part of dicrectory /db/migration
Hint
use a pattern like V1.0.1__name.sql 2 under scores
Hint
depending on Flyway version you should start with a sql file version greater than 1.0 example 1.0.1.
Hint per default spring boot jpa drops your database content if you using a in memory database. See http://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-sql.html section 28.3.3.
Related
When I want to use a Mysql database in a Springboot app, I am able to create it on start via a string in properties similar to this:
spring.datasource.jdbc-url=jdbc:mysql://localhost:3306/testDb?createDatabaseIfNotExist=true&autoReconnect=true&useSSL=false&allowPublicKeyRetrieval=true
Nevertheless PostgreSQL seems to ignore this:
spring.datasource.jdbc-url=jdbc:postgresql://localhost:5432/testdb?createDatabaseIfNotExist=true&autoReconnect=true&useSSL=false&allowPublicKeyRetrieval=true
Is there a way to create a PostgreSQL db on start of a SpringBoot app before Flyway attempts to initiate tables?
Postgres doesn't support creating a database on demand via the JDBC URL. You can learn about what configuration is possible in the documentation.
Its my first time I am using flyway. My application is spring boot with flyway for db version controlling and postgres as db.
I have write successfully a script V1_1_0__create_schema1.sql for writing schema:
Create schema if not exists schema1;
and second script to create table V1_1_1__create_table.sql for writing table:
create table if not exists schema1.table1( id int NOT NULL, name varchar(255), CONSTRAINT table1_pkey PRIMARY KEY (id) );
Now i want to write sql script for database creation with flyway convention. how can i do it? Thanks for your help!
Is it possible to create db using script in springboot app with flyway
for postgres?
Of course it is :D !
If yes how?
First you will need to add flyway on your project, as a depenency (without a version if you are using spring dependency management or BOM) :
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
</dependency>
Then spring Boot will automatically detect and autowire Flyway with its DataSource and invoke it on startup.
By default flyway looks in src/main/resources/db/migration folder for migration scripts, those script must follow a naming convention as V[version_number]__[Description_of_script].sql, please note that you have 2 underscore, so as example you can have V1__init_db.sql
then you can configure datasource properties in your application.properties ,to activate flyway using :
spring.flyway.enabled=true
spring.flyway.baseline-on-migrate=true
#if you have multiple schemas
spring.flyway.schemas=schema1,schema2
You can have a look at theses resources for more details there is a lot of options to explore there :
database-migrations-with-flyway.
build-a-spring-boot-app-with-flyway-and-postgres.
spring_boot_flyway_database
I have a Spring Boot application that uses Flyway for database migrations in Postgres.
It's about four years old now, so we're talking Flyway 4.0.3, Spring Boot 1.3.x, and Postgres 9.x. Versions could probably be upgraded, but I'd like to fix any existing issues before doing that.
In the meantime, Postgres was upgraded to higher than 9.x. Unfortunately, with that, a few of the existing migrations became outdated as they contain deprecated syntax. So now starting the app with a fresh database (i.e. in a development environment) leads to those migrations failing. In production it is fine as those migrations already have already been applied and won't be again.
I am curious as to what the best practices are to go about this. I can't just go and fix the syntax in the existing migrations, as this will lead to the checksums in the production environment failing. I know repair is a thing, however I am unsure how it works and how to use it with Spring Boot.
Failing SQL:
UPDATE config
SET (description) = 'my description'
WHERE ...
Correct SQL:
UPDATE config
SET description = 'my description'
WHERE ...
Error:
Message : ERROR: source for a multiple-column UPDATE item must be a sub-SELECT or ROW() expression
EDIT 24/04/2020 Spring Boot solution:
After Grant Fitchey posted the correct answer about how to use repair for this below, I am just going to add how I did this with Spring Boot specifically. I just created a bean of FlywayMigrationStrategy that calls
repair before it calls migrate:
#Bean
public FlywayMigrationStrategy cleanMigrateStrategy() {
return flyway -> {
flyway.repair();
flyway.migrate();
};
}
When deploying this to the production environment, during startup the checksums in the schema_versions table in Postgres were fixed. In another version I will remove the flyway.repair(); line again, as otherwise obviously this would create the risk of applying invalid migrations.
You are looking for the repair option. I don't know directly how to call it through spring boot, but the documentation is here. This should take care of exactly what you're looking for.
So the first step in this case would be to fix the migrations so they execute correctly in the development environment. Development should now be fine, and flyway should migrate successfully.
On production you should now get a validation error because the checksums differ. Flyway repair will 'repair' the schema history table so that the checksums it has stored match the new ones on disk, and therefore flyway validation passes again.
Specifically what flyway repair is doing is making the schema history table match what you have on disk. It updates all the checksums for applied migrations to the checksums of the ones you have on disk (and therefore, only use this if you are confident the changes are identical). It also removes all failed migration entries from the table (again, only use this once you have cleaned up the database yourself).
I have been able to successfully instantiate a connection to PostgreSQL using the reactive driver and config as per the micronaut docs.
See:
https://docs.micronaut.io/snapshot/guide/index.html#postgresSupport
I have been trying to figure out a way to use flyway to run db migrations but in order to instantiate a flyway bean I need a Datasource which doesn't seem to be possible to get using the reactive driver.
You don't need a datasource bean to instantiate flyway. You can provide it with the url, username, and password instead.
The micronaut configuration can be injected and read to get the configuration values. io.micronaut.configuration.postgres.reactive.PgPoolConfiguration
From their docs:
// Create the Flyway instance and point it to the database
Flyway flyway = Flyway.configure().dataSource("jdbc:h2:file:./target/foobar", "sa", null).load();
// Start the migration
flyway.migrate();
I am using the script of the spring.io/spring-roo/#running-from-shell fast guide, a 10 lines example.
The only modification is the jpa setup --provider line, changed to connect PostgreSQL (HIBERNATE --database POSTGRES). All the steps and code are at this roo_hello2pg.md github document.
The application.properties seems
spring.datasource.driver-class-name=org.postgresql.Driver
spring.datasource.url=jdbc\:postgresql\://localhost\:5432/hello2bd
spring.datasource.username=postgres
spring.datasource.password=postgres
What more I need? Some spring.jpa.hibernate lines? The browser generates error "status=500" when use database (insert a value).
As I could see in your gitHub repository, you have configured your connection to the Postgres database correctly.
But did you create the hello2db database and the Timer table in your system?
As the Spring Boot documentation sais, JPA databases will be automatically created only if you use an embedded database (H2, HSQL or Derby)
Check http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-creating-and-dropping-jpa-databases
In your case, to create the database automatically using a Postgres DB, you should include the spring.jpa.hibernate.ddl-auto=create-drop property in the application.properties file.
Hope it helps,