I want to use the database-migration grails plugin for database migration. When I start my Grails app the first time all the database tables are created automatically. The production setting in my DataSource.groovy is:
production {
dataSource {
dbCreate = "update"
url = "jdbc:mysql://localhost/myapp?useUnicode=yes&characterEncoding=UTF-8"
username = "test"
password = "test"
dialect = org.hibernate.dialect.MySQL5InnoDBDialect
properties {
validationQuery = "select 1"
testWhileIdle = true
timeBetweenEvictionRunsMillis = 60000
}
}
}
In my config.groovy I set:
grails.plugin.databasemigration.updateOnStart = true
grails.plugin.databasemigration.updateOnStartFileNames = ['changelog.groovy']
When I add properties to my domain classes I need to adjust the changelog file. What is the best way to do database migration in this case? What are the steps I have to do when I add or remove columns?
Migrations are performed programmatically by using a schema migration tool. When invoked with a specified desired schema version, the tool automates the successive application or reversal of an appropriate sequence of schema changes until it is brought to the desired state.
ORM is the bridge between the API and database. Changing the entity — aka data model (TypeORM class that stores an object's state in the database) — will update the schema during synchronization or migration.
What are the advantages of migration tools? Migrations are helpful because they allow database schemas to evolve as requirements change. They help developers plan, validate, and safely apply schema changes to their environments.
As you're probably aware, the dbcreate
directive is not recommended for production use:
You can also remove the
dbCreate
setting completely, which is recommended once your schema is relatively stable and definitely when your application and database are deployed in production.
So keep in mind that you will need to remove this (or set to 'none'
).
The first step is to get the changelog
to reflect the current state. If you've got an existing database, you want to use that to define the baseline. Otherwise, use GORM to define the tables.
These commands will generate a baseline for your database. Also I choose to use the groovy DSL format rather than liquibase XML, because readability.
If you've got a production database with data already, its a little bit tricky. You will need to access the database or a copy of it from your grails environment. If you manipulate a copy, you will need to apply the updates back to your production (and potentially manage it as a planned outage).
The command is:
grails [environment] dbm-generate-changelog changelog.groovy
...where environment
optionally specifies the dev/test/prod/custom environment the database is defined as.
Following that, mark the database as 'up-to-date' with regards to the changelog:
grails [environment] dbm-changelog-sync
Then reapply the database to production, if neccesary.
If you don't have an existing database (or don't care):
grails dbm-generate-gorm-changelog changelog.groovy
Then, to create the database from the changelog:
grails [environment] dbm-update
You've already correctly got the options set:
grails.plugin.databasemigration.updateOnStart = true
grails.plugin.databasemigration.updateOnStartFileNames = ['changelog.groovy']
These options simply mean that the plugin will attempt to apply the changes to the database when the application starts.
So now you've got a database up-to-date, and you're smashing out changes to the domain classes, adding new ones and changing validation properties.
Each time you want to record your changes, you want to compare your GORM classes to what exists in the database, and create a new changelog file to record the difference:
grails [environment] dbm-gorm-diff [meaningful name].groovy --add
Here environment
is the database you are comparing against, and meaningful name
should reflect in some way the change being applied (perhaps a JIRA issue key, or a version number, or a description).
The --add
flag will insert an include
statement in changelog.groovy
.
If you've configured updateOnStart
, then you're done! Otherwise, to manually process the update, reuse the command:
grails [environment] dbm-update
The approach that I would use is to migrate every table to a Grails domain with the mapping (very important!) properly set.
Then leave Grails to create the database the first time and then populate it with a previous backup of the database you want to migrate.
After this set Grails config to update the database every time it starts.
I know it seems a little bit messy but if I´ve to do it I would´ve do it this way.
Hope it helps :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With