Fork me on GitHub

Database Migrations

When you are using relational databases you need to track and organize schema evolutions.

This becomes increasingly important when many people are collaborating on one code base and also when you want to consistently upgrade your production database.

To that end Ninja integrates the excellent Flyway migration tool (http://flywaydb.org/).

Configuring migrations in Ninja

Activate migrations by setting the following property:

ninja.migration.run=true

Then set the credentials for your database:

db.connection.url=jdbc:postgresql://localhost:5432/ra
db.connection.username=ra
db.connection.password=

Setting up Flyway

Flyway itself manages database migration scripts in a directory called src/main/java/db/migration. You should use the following naming convention: V1__.sql is your first script, V2__.sql is your second script and so on.

V1__.sql may look like:

-- Just a simple table
create table GuestbookEntry (
    id int8 not null,
    email varchar(255),
    text varchar(255),
    primary key (id)
);

--needed for hibernate running on postgresql
create sequence hibernate_sequence;

A migration script is just plain old SQL. It is really important to stress that Flyway's migration scripts are NOT database vendor independent.

Therefore it is strongly discouraged to use different databases in test, dev and prod.

Collaboratively working on migrations

When two or more developers are working on the same script (let's say V2__.sql) they'll get conflicts once they are trying to merge their changes.

But this is intentional and allows to fix problems in V2__.sql. After resolving the issues and running your tests you can be confident that your production upgrade will also work fine.

Custom migration scripts location or schema name

If you want to store your migration scripts in a non-default directory (or directories), set the following optional property with a comma-separated list of locations.

ninja.migration.locations=classpath:com.example.migration,filesystem:/sql-migrations

You can also set a custom schema list using the following property. The first schema in the list will be automatically set as the default one during the migration.

ninja.migration.schemas=schema1,schema2,schema3

Migrations in test, dev and prod

In test mode Ninja automatically drops the schema and runs all migrations from scratch. In dev and production migration scripts are executed automatically when they are detected. Usually this happens when the first deployed Ninja instance connects with your database. Flyway's migrations are “clustersafe”. Therefore nothing will go wrong when you are deploying 20 instances of your application that try to run the evolutions at the same time.

Flyway migrations versus Hibernate DDL

Hibernate - the JPA implementation we are using is already providing a DDL (hbm2ddl) feature that can manage and create “migrations” for you.

But Hibernate's hbm2ddl is “just” a diff tool. Once your setup gets more complex Hibernate's feature is not enough. Even the creators of Hibernate strongly discourage the usage in production systems:

WARNING: We've seen Hibernate users trying to use SchemaUpdate to update the schema of a production database automatically. This can quickly end in disaster and won't be allowed by your DBA. (From the book Java Persistence with Hibernate).

Our recommendation is to enable Hibernate's DDL for your first initial developments.

Enable that by setting the following properties inside your persistence unit (persistence.xml):

<property name="hibernate.hbm2ddl.auto" value="create" /> 
<property name="hibernate.show_sql" value="true" />
<property name="hibernate.format_sql" value="true" />

Hint: Try using create (always drops data in your db) or update (tries to alter existing tables for new data) for hibernate.hbm2ddl.auto.

Hibernate will then print out nice SQL statements for the creation of your tables, sequences and so on.

Once your initial prototype is ready copy them to your first migration (eg V1__.sql) and deactivate Hibernate's DDL feature. From now on use Ninja's migrations and everything is safe.

More

Flyway offers a lot more. For instance Java based migrations, that really facilitate refactoring of blobs. Check out Flyway's excellent site at: http://flywaydb.org