Demo for Flyway migrations + JPA DDL Generation.
These instructions will get you a copy of the project up and running on your local machine for development and testing purposes
You can generate the initial database schema with:
mvn flyway:migrateThen run the main application to execute a JPQL query
mvn compile exec:javaFirst let's modify the model.
Open Person.java and uncomment lines 9, 21, 22 and 66:
package com.sevenrtc.stackoverflow.flyway.quickstart.entities;
import javax.persistence.*;
import java.util.Objects;
@Entity
@Table(name = "PERSON", uniqueConstraints = {
// Uncomment to test JPA DDL generation
@UniqueConstraint(name = "UK_PERSON_SSN", columnNames = "SSN")
})
public class Person {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "ID", nullable = false)
private Long id;
@Column(name = "NAME", nullable = false, length = 100)
private String name;
// Uncomment to test JPA DDL generation
@Column(name = "SSN", nullable = false, length = 15)
private String ssn;
/* ... more code ... */
@Override
public String toString() {
return "Person{" +
"id=" + id +
", name='" + name + '\'' +
", ssn='" + ssn + '\'' +
'}';
}
}Run the following command to generate a SQL Script with your changes:
mvn -PgenerateDDLFromJPAModel process-classesThe resulting script can be found at target/jpa/sql/schema-update.sql
alter table PUBLIC.PERSON
add column SSN varchar(15) not null;
alter table PUBLIC.PERSON
drop constraint if exists UK_PERSON_SSN;
alter table PUBLIC.PERSON
add constraint UK_PERSON_SSN unique (SSN);schema-update.sql will not work by default. Can you spot the problem with it?
While Hibernate is generating valid SQL code, you can't really add not null columns to PERSON due to the fact that
it has already been populated with some data. Even if you remove not null, the unique constraint will fail.
It is very important to consider your data when writing migration scripts. The same script may be applied in multiple environments with tables in different states (e.g., data may have been added manually). As a rule of thumb, it is best to avoid making assumptions about the data.
Fortunately, the problem above is easy to fix. We just need to make sure to load data to the new SSN column before
making it not null and enabling the unique constraint.
We could certainly write a complex ETL procedure to load data from different tables or external data sources. However, for the sake of simplicity I've modified the script above to generate fake data and saved it to 3__Add_SSN_to_person_table.sql:
alter table PERSON
add column SSN varchar(15);
update PERSON
set SSN = (select LPAD(ID, 15, '0'))
where SSN is null;
alter table PERSON
alter column SSN varchar(15) not null;
alter table PERSON
add constraint UK_PERSON_SSN unique (SSN);In order to update the database we need to copy the revised script to the db/migration folder and instruct Flyway
to migrate the schema
cp src/main/resources/db/new_migrations/V3__Add_SSN_to_person_table.sql src/main/resources/db/migration/
mvn flyway:migrateFinally, we can execute the main application one more time to verify the results:
mvn compile exec:javaThis project is licensed under the MIT License - see the LICENSE file for details