Description
This is a draft and obsolete!
Please see the documentation. http://www.mybatis.org/migrations/hooks.html
Migration hook
Overview
You can write scripts that are executed before or after up/down operation.
The following hooks are supported.
- before up/down : executed before the first migration
- before each up/down : executed before each migration
- after each up/down : executed after each migration
- after up/down : executed after the last migration
SQL and JSR-223 compliant scripting languages are supported for writing hook scripts.
Quick start
Here are what you need to do to use hook scripts.
- Create hooks directory.
- Create a hook script in hooks directory.
- Add settings to the environment properties file.
1. Create hooks directory.
Create a directory named hooks in the base directory.
2. Create a hook script in hooks directory.
The following script outputs the famous string to the log.
Save this script in the hooks directory as hello.js.
// hello.js
print('Hello, World!');
The example is written in JavaScript because JavaScript script engine is shipped with JDK.
3. Add settings to the environment properties file.
To configure Migrations, add the following line to the development.properties in the environment directory.
# development.properties
hook_before_up=JavaScript:hello.js
The details will be explained in the later section, but the above line tells Migrations to execute hello.js
at the beginning of migrate up
operation.
Now, if you run migrate up
, you will find the following lines in the log.
========== Applying JSR-223 hook : hello.js ==========
Hello, World!
NOTE: The hook script will not be executed if there was no pending migration.
Configuration
Keys for available hooks
As shown in the Quick Start section, the key of a hook setting specifies when to execute the script. Here is the list of available hooks.
- hook_before_up
- hook_before_each_up
- hook_after_each_up
- hook_after_up
- hook_before_down
- hook_before_each_down
- hook_after_each_down
- hook_after_down
Minimum setting : language and file name
The value part of the setting line consists of two or more segments separated with a colon :
.
The first segment is the language name (e.g. SQL, JavaScript, Groovy, etc.). The second segment is the file name. These two segments are required.
Here are some examples:
hook_before_up=SQL:insert_log.sql
hook_after_up=JavaScript:restart_server.js
Constant variables
The other segments are used to define constant variables specific to this particular hook script. These variables can have arbitrary names, but there also are some special variable names for JSR-223 hooks that are explained in the later section.
The following settings reference the same hook script printvar.js
with different variable values.
# development.properties
hook_before_up=JavaScript:printvar.js:when=before:what=up
hook_after_down=JavaScript:printvar.js:when=after:what=down
Constant variables can be referenced as global variables in JavaScript.
// printvar.js
print('This is ' + when + ' ' + what + ' hook.');
The above script will print This is before up hook.
on migrate up
and This is after down hook.
on migrate down
.
The below is an example for SQL hook scripts.
# development.properties
hook_before_up=SQL:update_timestamp.sql:col=before
hook_after_up=SQL:update_timestamp.sql:col=after
// update_timestamp.sql
update worklog set ${col} = current_date();
If there are global variables defined in the environment properties file, they can be used in hook scripts in the same manner.
foo=bar
Advanced usage of JSR-223 scripts
Get paths to the directories
An instance of SelectedPaths object is accessible as a global variable migrationPaths
.
print(migrationPaths.getBasePath());
print(migrationPaths.getEnvPath());
print(migrationPaths.getScriptPath());
print(migrationPaths.getDriverPath());
print(migrationPaths.getHookPath());
Accessing Change object (each hook only)
In an each hook script, an instance of Change object is accessible via the global variable migrationContext
.
print(migrationContext.getChange().getId());
print(migrationContext.getChange().getFilename());
NOTE: The Change instance is a clone and will be discarded after each exection, so modifying it would be meaningless.
Execute SQL statement
You can execute arbitrary SQL statement via the built-in global object migrationContext
.
migrationContext.executeSql("insert into worklog (str1) values ('done!');");
If you need more than just executing SQL statement, you can get an instance of java.sql.Connection
from migrationContext
.
con = migrationContext.getConnection();
try {
stmt = con.createStatement();
rs = stmt.executeQuery("select * from changelog");
while (rs.next()) {
print("id = " + rs.getString("id"));
}
} finally {
con.close();
con = null;
rs = null;
stmt = null;
}
Invoking function
When configuring JSR-223 hook scripts, it is possible to specify a top level function to invoke. The following script contains two functions foo
and bar
.
// foobar.js
function foo() {
print('foo');
}
function bar(id, name) {
print(id + ':' + name);
}
To invoke a function, you need to specify the function name using a special variable name _function
.
hook_before_up=js:foobar.js:_function=foo
hook_after_up=js:foobar.js:_function=bar:_arg=100:_arg=John
Notice that the two arguments passed to bar()
function are specified with another special variable name _arg
.
NOTE: Some JSR-223 implementation may not support function invocation.
Invoking method
Similar to function invocation, it is also possible to invoke a method of an top level object.
doggy.js
var dog = new Object();
dog.bark = function(who, times) {
print('bow-wow ' + times + ' times at ' + who);
}
In the hook setting, use _object
to specify the object name and _method
for the method name.
hook_before_up=js:doggy.js:_object=dog:_method=bark:_arg=Lucy:_arg=128
NOTE: Some JSR-223 implementation may not support method invocation.
Retain variable value throughout operation
When single up/down operation executes multiple migrations, variables are reset on each migration.
There are two ways to retain variable value throughout the operation.
-
Initialize the variable in before_up/down script and use it in before/after_each_up/down script.
// before_up hook script var counter = 1
// before_each_up hook script print(counter++);
-
Initialize only when it is undefined.
if (typeof counter == 'undefined') this.counter = 1; println(counter++);
Use other languages than JavaScript
To use other JSR-223 compliant scripting language than JavaScript, you need to copy required .jar files to $MIGRATIONS_HOME/lib
directory.
To write hook scripts in Groovy, for example, you will need groovy.jar and groovy-jsr223.jar.
Once the JARs are placed in $MIGRATIONS_HOME/lib
directory, the rest is pretty much the same as JavaScript.
Save hello.groovy
in hooks directory with the following content...
// hello.groovy
println('Hello groovy!')
...and add the setting to the environment file.
hook_before_up=groovy:hello.groovy