What is Liquibase ?
- LiquiBase — available
since 2006 — is an open source, freely available tool for
migrating from one database version to another, It is an open source
database-independent library for tracking, managing and applying
database changes.
- A handful of other open
source database-migration tools are on the scene as well, including
openDBcopy and dbdeploy. LiquiBase supports 10 database types,
including DB2, Apache Derby, MySQL, PostgreSQL, Oracle, Microsoft®
SQL Server, Sybase, and HSQL.
- All changes to the database
are stored in XML files and identified by a combination of an "id"
and "author" tag as well as the name of the file itself.
- A list of all applied
changes is stored in each database which is consulted on all
database updates to determine what new changes need to be applied.
- LiquiBase executes changes
based on this XML file to handle different revisions of database
structures and data.
- When you first run a
changelog, LiquiBase manages those changelogs by adding two tables
into your database.
databasechangelog: maintains the database changes that were run.
databasechangeloglock: ensures that two machines don't attempt to modify the database at one time.
Getting started with LiquiBase takes four steps:
- Create a database change log file.
- Create a change set inside the change log file.
- Run the change set against a database via the command line or a build script.
- Verify the change in the
database.
Sample changeLog file: The above is an example of creating table EMPLOYEE and adding columns into it.
<?xml version="1.0" encoding="UTF-8"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-2.0.xsd">
<changeSet author="waheed" id="123456789-1">
<comment> You can add comments to changeSets.</comment>
<createTable tableName="EMPLOYEE">
<column autoIncrement="true" name="EMPLOYEE_ID" type="BIGINT">
<constraints nullable="false" primaryKey="true" />
</column>
<column name="NAME" type="VARCHAR(255)" />
<column name="GENDER" type="VARCHAR(2)" />
<column name="COUNTRY" type="VARCHAR(255)" />
<column name="ABOUT_YOU" type="VARCHAR(255)" />
</createTable>
</changeSet>
</databaseChangeLog>
Running LiquiBase from the command line:
After defining the change set, I can run LiquiBase from the command line:
Running
LiquiBase from the command line
liquibase --driver=com.mysql.jdbc.Driver \ --classpath=mysql_connector.jar \ --changeLogFile=database.changelog.xml \ --url=jdbc:mysql://localhost:3306/Employees;create=true \ --username= --password= \ update |
In this example, I run LiquiBase passing in:
- The database driver
- The classpath for the location of the database driver's JAR file
- The name of the change log file “database.changelog.xml”
- The URL for the database
- A username and password
Instead of using the command-line option, I can make the database changes as part of the automated build by calling the Ant task provided by LiquiBase.
Ant script to execute the
updateDatabase
Ant task<target name="update-database"> <taskdef name="updateDatabase" classname="liquibase.ant.DatabaseUpdateTask" classpathref="project.class.path" /> <updateDatabase changeLogFile="database.changelog.xml" driver="com.mysql.jdbc.Driverr" url="jdbc:mysql://localhost:3306/Employees" username="" password="" dropFirst="true" classpathref="project.class.path"/> </target> |
I create a target called
update-database
.
In it, I define the specific LiquiBase Ant task I wish to use,
calling it updateDatabase
.
I pass the required values, including the changeLogFile
and connection
information for the database. The classpath defined in classpathref
must contain liquibase-version.jar.Applying refactorings to an existing database
As new features are added to an application, the need often arises to apply structural changes to a database or modify table constraints. LiquiBase provides support for more than 30 database refactorings.
Add Column
It's sometimes next to impossible to consider all of the possible columns in a database at the beginning of a project. And sometimes users request new features — such as collecting more data for information stored in the system — that can require new columns to be added.
Using
the Add Column database refactoring in a LiquiBase change set
<changeSet author="waheed" id=”123456789-2”> <addColumn tableName="EMPLOYEE"> <column name="PHONE_NUMBER" type="varchar(255)" defaultValue=”SOME_DEFAULT_VALUE”/> </addColumn> </changeSet> |
PHONE_NUMBER
column is defined as a varchar
datatype.Drop Column
Suppose, you choose to remove the
PHONE_NUMBER
column you added above. This is as simple as calling the dropColumn
refactoring:Dropping a database column
<dropColumn tableName="EMPLOYEE" columnName="PHONE_NUMBER"/>
|
Create Table
Adding a new table to a database is also a common database refactoring. Creates a new table called
USER
,
defining its columns, constraints, and default values:
Creating
a new database table in LiquiBase
<changeSet author="waheed" id=”123456789-3”> <createTable tableName="USER"> <column name="ID" type="int"> <constraints primaryKey="true" nullable="false"/> </column> <column name="NAME" type="varchar(255)"> <constraints nullable="false"/> </column> <column name="ADDRESS" type="varchar(255)"> <constraints nullable="true"/> </column> <column name="active" type="boolean" defaultValue="1"/> </createTable> </changeSet> |
This example uses the
createTable
database refactoring as part of a change set (createTable
was also used back).Rename Column
<changeSet author="waheed" id=”123456789-5”> <comment>Add a username column so we can use "person" for authentication</comment> <addColumn tableName="EMPLOYEE"> <column name="usernae" type="varchar(8)"/> </addColumn> </changeSet> |
Now, we need to fix the usernae become username
<changeSet author="waheed" id=”123456789-6”> <comment>Fix misspelled "username" column</comment> <renameColumn tableName="EMPLOYEE" oldColumnName="usernae" newColumnName="username" columnDataType="varchar(8)"/> </changeSet> |
Manipulating data
After applying structural database refactorings (such as Add Column and Create Table), you often need to insert data into tables affected by these refactorings. Furthermore, you might need to change the existing data in lookup tables or other types of tables. Below example shows how to insert data using a LiquiBase change set:
Inserting data in a LiquiBase change set
<changeSet author="waheed" id=”123456789-4”> <code type="section" width="100%"> <insert tableName="USER"> <column name="ID" valueNumeric="3"/> <column name="NAME" value="ABDUL"/> </insert> <insert tableName="USER"> <column name="ID" valueNumeric="4"/> <column name="NAME" value="WAHEED"/> </insert> </changeSet> |
Suppose, You may have already written SQL scripts to manipulate data, or the LiquiBase XML change set may be too limiting. And sometimes it's simpler to use SQL scripts to apply mass changes to the database. LiquiBase can accommodate these situations too.
Running a custom SQL file from a LiquiBase change set
<changeSet author="Waheed" id=”123456789-5”> <sqlFile path="insert-distributor-data.sql"/> </changeSet> |
How to integrate With Spring:
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close">
<property name="driverClass" value="com.mysql.jdbc.Driver" />
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/Employees" />
<property name="user" value="root" />
<property name="password" value="root123" />
<property name="minPoolSize" value="8" />
<property name="maxPoolSize" value="16" />
<property name="maxIdleTime" value="3600" />
</bean>
<!-- Updater is used to automatically update DB upon startup if
Application version has changed -->
<bean id="LiquibaseUpdater" class="liquibase.integration.spring.SpringLiquibase">
<property name="dataSource" ref="dataSource" />
<property name="changeLog" value="classpath:db-changelog.xml" />
</bean>
<!-- Needed here to make sure Liquibase updater runs prior to DAO's startup, Your DAO class -->
<bean class="com.waheed.spring.hibernate.DaoImpl" id="dao"
depends-on="LiquibaseUpdater">
</bean>
Resources:
http://www.liquibase.org