Spring Boot Application: how to create shema using flyway on startup? - java

There is spring boot application.
Here is configuration:
spring
flyway:
locations: classpath:db/migration
baseline-on-migrate: true
schemas: ${app.db.schema}
placeholders:
schema: ${app.db.schema}
init-sqls: CREATE SCHEMA IF NOT EXISTS ${app.db.schema}
And it doesn't work.
I need to create db schema before flyway will run migrations.

Flyway tries to read database migration scripts from classpath:db/migration folder by default.
All the migration scripts must follow a particular naming convention - V<VERSION_NUMBER>__<NAME>.sql.
Create a new file named V1__Create_Tables.sql inside src/main/resources/db/migration directory and add the sql script, for example:
-- ----------------------------
-- Schema for helloservice
-- ----------------------------
CREATE SCHEMA IF NOT EXISTS helloworld;
-- ----------------------------
-- Table structure for user
-- ----------------------------
CREATE TABLE helloworld.users (
id BIGSERIAL PRIMARY KEY NOT NULL UNIQUE,
username VARCHAR(255) UNIQUE NOT NULL,
password VARCHAR(255) NOT NULL,
first_name VARCHAR(255),
middle_name VARCHAR(255),
last_name VARCHAR(255),
email VARCHAR(255),
enabled bool NOT NULL DEFAULT true,
account_locked bool NOT NULL,
account_expired bool NOT NULL,
credential_expired bool NOT NULL,
created_on timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_on timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP
);
COMMENT ON TABLE helloworld.users IS 'User table';
When you run the application, flyway will automatically check the current database version and apply any pending migrations. By default, no additional properties are required. You can also create a schema in this script. Or flyway will do it for you if you specify a non-existent scheme.
If you are using hibernate, check this property:
spring.jpa.hibernate.ddl-auto=validate
For more information, see the instructions.

There is documentation link: https://flywaydb.org/documentation/commandline/migrate#schemas
Actually FlyWay is responsible for creating schemas if they don't exist.
Here is an example in changelog-history table:

Related

ALTER TABLE CREATE CONSTRAINT IF NOT EXIST possible?

I have an application which starts (AppStarter) a web server with a web application. The Web Application has migration scripts (flyway).
I want to write some data from AppStarter through JDBC in a table. But I want to create the table if it does not exist. The table also has some constraints.
Within the AppStarter I execute following command:
CREATE CACHED TABLE PUBLIC.CORE_USERROLE_TO_PARAMETER (
ID VARCHAR(32) PRIMARY KEY NOT NULL,
VERSION INTEGER,
USER_ID VARCHAR(32)NOT NULL,
ROLE_ID VARCHAR(32) NOT NULL,
PARAMETER VARCHAR(255) NOT NULL
);
ALTER TABLE PUBLIC.CORE_USERROLE_TO_PARAMETER ADD CONSTRAINT PUBLIC.CURTBP_USER_ID FOREIGN KEY(USER_ID) REFERENCES PUBLIC.CORE_USER(ID) NOCHECK;
ALTER TABLE PUBLIC.CORE_USERROLE_TO_PARAMETER ADD CONSTRAINT PUBLIC.CURTBP_ROLE_ID FOREIGN KEY(ROLE_ID) REFERENCES PUBLIC.CORE_USER_ROLE(ID) NOCHECK;
The web app also reads some information from this table and creates the tables.
Now I have a sql migration script
CREATE CACHED TABLE IF NOT EXISTS PUBLIC.CORE_USERROLE_TO_PARAMETER (
ID VARCHAR(32) PRIMARY KEY NOT NULL,
VERSION INTEGER,
USER_ID VARCHAR(32)NOT NULL,
ROLE_ID VARCHAR(32) NOT NULL,
PARAMETER VARCHAR(255) NOT NULL
);
But how do I create the constraint only if they does not already exist?
Thanks in advance
Currently I can get if the constraints exists with
select * from INFORMATION_SCHEMA.CONSTRAINTS WHERE CONSTRAINT_NAME='CURTRP_USER_ID'
but how do I build this into a if query with H2
Edit:
I could move the constraint part in total to the migration script, but this seems somehow wrong.
I am working with H2 Database.
Following my comment, this should be possible:
ALTER TABLE PUBLIC.CORE_USERROLE_TO_PARAMETER
ADD CONSTRAINT IF NOT EXISTS PUBLIC.CURTBP_USER_ID
FOREIGN KEY(USER_ID) REFERENCES PUBLIC.CORE_USER(ID) NOCHECK;
ALTER TABLE PUBLIC.CORE_USERROLE_TO_PARAMETER
ADD CONSTRAINT IF NOT EXISTS PUBLIC.CURTBP_ROLE_ID
FOREIGN KEY(ROLE_ID) REFERENCES PUBLIC.CORE_USER_ROLE(ID) NOCHECK;
Use this query to get the foreign key constraints
SELECT * FROM INFORMATION_SCHEMA.CONSTRAINTS WHERE CONSTRAINT_TYPE = 'REFERENTIAL'
You can try ALTER TABLE IF EXISTS like CREATE IF EXISTS. If its a responsibility of your application only, and not handled by another app or script.

Order execution of create table using mysql, h2 and flyway

I have created a an sql script (using mysqldump) to determine my base version of my database. I use this script with flywaydb to totally manage the db creation and other migration actions. The script contains of several tables some of them are fk's to others. the order in which they appear in the sql script generated by mysqldump is the following (only two of the tables appear that are causing the issue described later below)
CREATE TABLE `signaling_interface` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`test_server_id` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `UK_sigInterfaceConstraint` (`test_server_id`),
KEY `FK_3crdx5y8had0g1mit1k2gebt5` (`test_server_id`),
CONSTRAINT `FK_3crdx5y8had0g1mit1k2gebt5` FOREIGN KEY (`test_server_id`) REFERENCES `test_server` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `test_server` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `UK_3754w88bn333h1dgambvwj6i8` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
I want to Junit test my migrations and chose h2 in memory database to do that. But when I try to migrate it gives me an error when creating signaling_interface table because test_server does not exist. It doesn't give me this error when executing migrations in MySQL. Is there a difference between mysql and h2?

Appfuse 3.5 and DB2

I am trying to create a webapp using appfuse. By default appfuse configures the app to work with a MySQL database, however I'd like use a DB2 database. Since Appfuse uses hibernate and Spring this should be a fairly straightforward configuration change but I haven't been able to get it to work. I get the following error on all my SQL calls:
create table role (
id bigint generated by default as identity,
description varchar(64),
name varchar(20),
primary key (id)
);
HHH000389: Unsuccessful: create table role (id bigint generated by default as identity, description varchar(64), name varchar(20), primary key (id))
DB2 SQL Error: SQLCODE=-104, SQLSTATE=42601, SQLERRMC=;;imary key (id));END-OF-STATEMENT, DRIVER=4.19.26
Here is how I have configured hibernate and the jdbc connection:
<jdbc.groupId>com.ibm.db2</jdbc.groupId>
<jdbc.artifactId>db2jcc4</jdbc.artifactId>
<jdbc.version>10.5</jdbc.version>
<jdbc.driverClassName>com.ibm.db2.jcc.DB2Driver</jdbc.driverClassName>
<jdbc.url>jdbc:db2://<IP Address>:<Port>/<DBName>:currentSchema=<schemaName>;</jdbc.url>
<jdbc.username><username></jdbc.username>
<jdbc.password><password></jdbc.password>
<jdbc.validationQuery><![CDATA[SELECT 1 FROM sysibm.sysdummy1;]]></jdbc.validationQuery>
<hibernate.dialect>org.hibernate.dialect.DB2Dialect</hibernate.dialect>
I don't understand where I'm going wrong. I can use the same db2jcc4.jar and connection parameters to connect to the DB through netbeans and copy and paste the sql from above and it executes without error. So I don't believe it's a syntax error as the SQLCODE=104, SQLSTATE42601 indicates. I'm at a loss of what I'm doing wrong. Any help you can give me is greatly appreciated!
I'm not sure if this is the correct answer but it worked: I removed the validation Query.
If anyone knows of a better answer or why this worked please share.
Thank you!

Execute db statements from file

I use embedded Apache derby for my application. I have a SQL script called createdb.sql that creates all tables in a database and populates it with initial data, e.g.:
SET SCHEMA APP;
CREATE TABLE study (
study_id bigint not null GENERATED ALWAYS AS IDENTITY (START WITH 1, INCREMENT BY 1),
name varchar(50) not null,
note varchar(1000) DEFAULT '',
created TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
deleted boolean DEFAULT false,
UNIQUE(name),
CONSTRAINT primary_key PRIMARY KEY (study_id)
);
INSERT INTO "APP"."STUDY" (NAME) VALUES ('default');
CREATE TABLE img (
img_id bigint not null GENERATED ALWAYS AS IDENTITY (START WITH 1, INCREMENT BY 1),
filename varchar(200) not null,
path varchar(300) not null,
flipped boolean DEFAULT false,
type smallint not null,
note varchar(1000) DEFAULT '',
created TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (img_id)
);
ALTER TABLE img ADD COLUMN dpix integer DEFAULT -1;
ALTER TABLE img ADD COLUMN dpiy integer DEFAULT -1;
The question is how do I load this file and execute all the statements using java? I'm trying different function but they all don't work. For example,
Statement s = conn.createStatement();
s.execute(sqlStr);
or
Statement s = conn.createStatement();
s.executeUpdate(sqlStr);
where sqlStr is a String variable containing the contents of the createdb.sql file. How do I execute all the SQL commands contained in the script so that I can create all the tables and initialize them? Btw, the SQL script works, as I use it in SQuirreL SQL Client to manualy create and initialize the database. Now I would like to do it from within my application.
The below tutorial give how to run a mysql script(.sql file) . What you have to do is that Change the mysql db connection to derby db and run. It will work.
http://www.mkyong.com/jdbc/how-to-run-a-mysql-script-using-java/
Here is an alternative way to run a MySQL script without using any third party library.
http://coreyhulen.wordpress.com/2010/04/07/run-a-sql-script-for-mysql-using-java/
With Derby, you generally use the 'ij' tool to do this:
http://db.apache.org/derby/docs/10.9/tools/ttoolsij98878.html
If you want to do this from a Java program of your own, rather than from the command line, you'll want to study the 'runscript' feature of ij; see this related question:
How to run sql scripts in order to update a Derby schema from java code?

Eclipse + MySql + Hibernate, a good intro?

I'm looking for a tutorial explaining how to work with these 3 technologies, found this one, but it's working with HyperSql DB (yeah, I edited hibernate.cfg.xml to connect with MySql... but I just received a bunch of errors).
Your table creation script is wrong for the hibernate generator strategy you're currently using. As I said, your primary key should be defined as autoincrement:
CREATE TABLE COURSES (
COURSE_ID int(11) NOT NULL AUTO_INCREMENT,
COURSE_NAME varchar(20) DEFAULT NULL,
PRIMARY KEY (COURSE_ID)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
You should let SchemaExport generate your DDL for you, it will typically prevent such mistakes ;)
You might try setting <generator class="identity">. But native should also be working if you have set the database column to be auto_increment.
Problem solved using "Toad for MySQL" for creating the table, when setting the column to be the primary key, I just cleaned the "Default value" and did set the AutoIncrement property to true.

Categories