No artigo anterior comentei
sobre a importância das práticas da engenharia como refactoring e
versionamento aplicados ao Banco de Dados. Neste, veremos como
usar o Liquibase na prática com Apache Maven 2.
A utilização em
conjunto com Maven 2 é muito produtiva por dois fatores. O primeiro é
que você pode criar um projeto Java no eclipse e utilizar o seu plugin
de SCM sendo do CVS ou Subversion para versionar o projeto. O segundo
motivo é que você pode colocar este projeto no seu servidor de build
continuo, tendo, assim, as mudanças do desenvolvimento e banco
acontecendo de forma igual e no mesmo momento.
A estrutura básica do projeto
Você poderia estruturar o projeto de várias formas, no site do liquibase existem algumas boas práticas de como estruturas os conjuntos de mudanças. Vamos à estrutura do projeto que criei:
- src/main/resources/changelogs
- src/main/resources/database-conf
- src/main/resources/sql
- src/main/resources/start-script
- pom.xml
No
arquivo pom.xml ficam as configurações para o uso do plugin do
liquibase com Maven. Você não precisa mexer neste arquivo, pois eu
parametrizei as informações que precisam ser modificadas em arquivos
.properties. Claro que você pode customizar a forma de uso modificando
o pom.xml.
Pensando que um DBA/AD vai ter acesso, é mais
interessante que ele lide com os arquivos properties do que com a
configuração do maven 2 diretamente.
No diretório changelogs
estão os arquivos de mudanças do banco. Este diretório serve para
armazenarmos arquivos .xml com as tags próprias do liquibase para o
refactoring.
As configurações básicas de acesso ao banco de
dados, bem como parametrização do liquibase, estão no diretório
database-conf em forma de arquivos properties também.
No
diretório sql estão os scripts SQL com as mudanças a serem aplicadas no
banco, mais adiante no post vou dar mais explicações sobre estes
arquivos.
Por fim, no diretório start-script estão os scripts
básicos de criação do banco. Estes são scripts que devem ser criados
antes de usarmos o liquibase, aqui existe a criação do banco e dos
schemas e roles de acessos, isto poderia ser feito com o liquibase, mas
neste caso teríamos que usar um usuário com super privilégios no banco.
Esta não seria uma boa prática, logo é melhor deixar para o DBA rodar
manualmente este script.
O changelog.xml e os change-sets
Os
Refactorings de banco ficam em arquivos .xml. Estes arquivos podem ser
agrupados por versão, data, release, grupo de funcionalidades, entre
outras estratégias de agrupamento. Como é um arquivo .xml texto claro
isto permite que ele seja versionado via uma ferramenta de SCM como o
CVS ou Subversion. Existe um schema XSD
para tags de operação do liquibase. Isso é muito bom por que quem usa
um IDE como o eclipse pode ter auto-complete das tags, o que facilita o
uso de XML.
O ideal seria utilizar um IDE gráfico. Existe um IDE que é baseado em eclipse, porem a solução esta
parada (em 02/08/2009), logo vamos ter que lidar com o XML. Mas existem
outras formas de informar mudanças para o banco e vou mostrar isto mais à frente. Vejamos um changelog com alguns changesets.
<?xml version="1.0" encoding="UTF-8"?>
<databasechangelog xmlns="http://www.liquibase.org/xml/ns/dbchangelog/1.9" xsi="http://www.w3.org/2001/XMLSchema-instance" schemalocation="http://www.liquibase.org/xml/ns/dbchangelog/1.9 http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-1.9.xsd">
<changeset id="1" author="Diego.Pacheco">
<createtable tablename="pessoas">
<column name="id" type="int">
<constraints primarykey="true" nullable="false">
</column>
<column name="nome" type="varchar(50)">
<constraints nullable="false">
</column>
<column name="active" type="boolean" defaultvalue="1">
</createtable>
</changeset>
<changeset id="2" author="Crom.God">
<addcolumn tablename="pessoas">
<column name="mitologico" type="boolean">
<constraints nullable="true">
</column>
</addcolumn>
</changeset>
</databasechangelog>
Os
Changesets são grupos de mudanças, podemos aplicar um identificador e
um usuário responsável pela mudança. Isso é considerado uma boa prática
porque desta forma podemos controlar e identificar quem fez a mudança.
Neste
exemplo existem dois changesets e dois autores diferentes. No primeiro
changeset foi criada uma tabela com uma coluna id que é chave primaria
e outra coluna nome que é do tipo varchar.
No outro changeset é
adicionado mais uma coluna a tabela pessoas que foi criada no changeset
anterior, esta coluna é do tipo boolean.
Poderíamos aplicar as
duas mudanças no mesmo changeset, mas isso vai depender de algumas
escolhas, por exemplo se elas estão em dois changesets diferentes
significa que são feitas em momentos diferentes, ou seja, é mais
aplicada para quando aplicamos mudanças incrementais, que é algo comum
no desenvolvimento de uma aplicação. Poderíamos colocar no mesmo
changeset, isso teria sentido se as mudanças forem do mesmo momento ou
propósito.
Ter as mudanças separadas em changesets pode ser útil
também porque nos possibilita dar rollback das mudanças depois pelo
número do changeset.
Para aplicar estas mudanças no banco de
dados vamos usar a feature de update do liquibase, neste caso eu criei
um profile do maven para isso. Vamos ver isto na prática agora. Na
minha aplicação estou usando Postgres mas você poderia usar outro
banco, no site da ferramenta existe suporte a uma lista grande de bancos.
Então
vamos as configurações e a execução do update na base de dados. Antes
você deve criar a estrutura básica da aplicação que estão no script
chamado setup.sql, confira a baixo:
//--------------------------------------------------------------------------
// SetpUP inicial DO banco de dados. Este script deve rodar antes
// de aplicarmos AS mudanças via liquibase.
//
// @autor Diego Pacheco
// @version 1.0
// @since 02/08/2009
//--------------------------------------------------------------------------
CREATE ROLE m2liquibase LOGIN
ENCRYPTED PASSWORD 'md56e7ae817b181fe78f6f7bdab8cfdc236'
NOSUPERUSER INHERIT NOCREATEDB NOCREATEROLE;
CREATE DATABASE liquibase
WITH OWNER = m2liquibase
ENCODING = 'UTF8'
LC_COLLATE = 'Portuguese_Brazil.1252'
LC_CTYPE = 'Portuguese_Brazil.1252'
CONNECTION LIMIT = -1;
GRANT ALL ON DATABASE liquibase TO public;
GRANT ALL ON DATABASE liquibase TO m2liquibase;
CREATE ROLE m2liquibasediff LOGIN
ENCRYPTED PASSWORD 'md54a95696426bfd75ee783033c857de2d4'
NOSUPERUSER INHERIT NOCREATEDB NOCREATEROLE;
CREATE DATABASE liquibasediff
WITH OWNER = m2liquibasediff
ENCODING = 'UTF8'
LC_COLLATE = 'Portuguese_Brazil.1252'
LC_CTYPE = 'Portuguese_Brazil.1252'
CONNECTION LIMIT = -1;
GRANT ALL ON DATABASE liquibasediff TO public;
GRANT ALL ON DATABASE liquibasediff TO m2liquibasediff;
Uma vez que este script esteja rodado e o banco de dados no ar, você pode executar o liquibase através do maven com o seguinte comando $ mvn install -P update. Este comando vai gerar um resultado semelhante a o abaixo:
[INFO] Scanning for projects...
[INFO] ------------------------------------------------------------------------
[INFO] Building liquibase-postgres-maven2
[INFO]
[INFO] Id: com.blogspot.diegopacheco.sandbox.java:liquibase-postgres-maven2:jar:1.0
[INFO] task-segment: [install]
[INFO] ------------------------------------------------------------------------
[INFO] [properties:read-project-properties]
[INFO] [resources:resources]
[INFO] Using default encoding to copy filtered resources.
[INFO] [liquibase:update]
[INFO] ------------------------------------------------------------------------
[INFO] Parsing Liquibase Properties File
[INFO] File: src/main/resources/database-conf/db.operations.properties
[INFO] 'liquibase.diff.conf.url' in properties file is not being used by this task.
[INFO] 'liquibase.dbdoc.ouputDir' in properties file is not being used by this task.
[INFO] 'liquibase.diff.conf.usr' in properties file is not being used by this task.
[INFO] 'liquibase.update.sql.conf.migrationSqlOutputFile' in properties file is not being used by this task.
[INFO] 'liquibase.dbdoc.changeLogFile' in properties file is not being used by this task.
[INFO] 'liquibase.diff.conf.pwd' in properties file is not being used by this task.
[INFO] 'liquibase.tag.conf.id' in properties file is not being used by this task.
[INFO] 'liquibase.default.changelog.propertyFile' in properties file is not being used by this task.
[INFO] 'liquibase.rollback.conf.rollbackTag' in properties file is not being used by this task.
[INFO] ------------------------------------------------------------------------
[INFO] Executing on Database: jdbc:postgresql://localhost:5432/liquibase
02/08/2009 21:56:23 liquibase.database.template.JdbcTemplate comment
INFO: Create Database Lock Table
02/08/2009 21:56:23 liquibase.database.template.JdbcTemplate comment
INFO: Lock Database
02/08/2009 21:56:23 liquibase.lock.LockHandler acquireLock
INFO: Successfully acquired change log lock
02/08/2009 21:56:23 liquibase.database.template.JdbcTemplate comment
INFO: Create Database Change Log Table
02/08/2009 21:56:23 liquibase.database.AbstractDatabase checkDatabaseChangeLogTable
INFO: Creating database history table with name: databasechangelog
02/08/2009 21:56:24 liquibase.database.AbstractDatabase getRanChangeSetList
INFO: Reading from databasechangelog
02/08/2009 21:56:24 liquibase.database.template.JdbcTemplate comment
INFO: Changeset src/main/resources/changelogs/changelog.xml::1::Diego.Pacheco::(MD5Sum: 12dcf42c2189f3b294f2d95537c94955)
02/08/2009 21:56:24 liquibase.database.template.JdbcTemplate comment
INFO: Changeset src/main/resources/changelogs/changelog.xml::2::Crom.God::(MD5Sum: c15ccb11b31e631a1245e2d882bf4b)
02/08/2009 21:56:24 liquibase.database.template.JdbcTemplate comment
INFO: Release Database Lock
02/08/2009 21:56:24 liquibase.lock.LockHandler releaseLock
INFO: Successfully released change log lock
02/08/2009 21:56:24 liquibase.database.template.JdbcTemplate comment
INFO: Release Database Lock
02/08/2009 21:56:24 liquibase.lock.LockHandler releaseLock
INFO: Successfully released change log lock
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] [compiler:compile]
[INFO] No sources to compile
[INFO] [resources:testResources]
[INFO] Using default encoding to copy filtered resources.
[INFO] [compiler:testCompile]
[INFO] No sources to compile
[INFO] [surefire:test]
[INFO] No tests to run.
[INFO] [jar:jar]
[INFO] Building jar: D:\Diego\Java\bin\workspaces-eclipse\eclipse_workspace\liquibase-postgres-maven2\target\liquibase-postgres-maven2-1.0.jar
[INFO] [exec:java]
[INFO] [install:install]
[INFO] Installing D:\Diego\Java\bin\workspaces-eclipse\eclipse_workspace\liquibase-postgres-maven2\target\liquibase-postgres-maven2-1.0.jar to C:\Users\Diego Pacheco\.m2\repository\com\blogspot\diegopacheco\sandbox\java\liquibase-postgres-maven2\1.0\liquibase-postgres-maven2-1.0.jar
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 4 seconds
[INFO] Finished at: Sun Aug 02 21:56:25 BRT 2009
[INFO] Final Memory: 3M/11M
[INFO] ------------------------------------------------------------------------
Esta foi a primeira vez que executamos o
liquibase, neste momento ele cria 2 tabelas para controle do banco de
dados uma delas para controle de locks e outra para controle de
versões, changelogs, tags e rollbacks, vamos ver esta segunda tabela.
Você pode fazer uma query nela, com o seguinte SQL:
SELECT id, author, filename, dateexecuted, md5sum, description, comments, tag, liquibase FROM databasechangelog;
Você vai obter um resultado semelhante a este:

Agora
podemos passar a tag no banco de dados. Esta é uma excelente prática de
gerência de configurações e pode ser usada quantas vezes for necessária
durante o projeto, o mínimo seria usar pelo menos a cada vez que você
for liberar uma versão. Eu criei um profile do maven para passar a tag,
a tag tem um identificador que pode ser um número por exemplo 2.5.7 ou
um texto por exemplo versao-1.0. Basta rodar o seguinte comando $ mvn install -P tag a tag sera obtida do arquivo de properties que criei no diretório database-conf.
# Configuração para tag no banco
liquibase.tag.conf.id=1.0
Depois de passar a tag se refizermos a query na tabela databasechangelog vamos obter o seguinte resultado:

Como
você pode perceber, a última mudança ficou com a tag 1.0. Assim o
Liquibase aplica a tag sempre na última modificação. Logo, se você
tivesse aplicado 100 mudanças, todas fariam parte desta tag. Isso é
fundamental para a gerência de configurações e para os procedimentos de
rollback..png>
.png>
Vamos aplicar mais mudanças no banco de dados e depois passar a tag para versão 2.0. Confira o changelog abaixo:.png>
<?xml version="1.0" encoding="UTF-8"?>
<databasechangelog xmlns="http://www.liquibase.org/xml/ns/dbchangelog/1.9" xsi="http://www.w3.org/2001/XMLSchema-instance" schemalocation="http://www.liquibase.org/xml/ns/dbchangelog/1.9 http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-1.9.xsd">
<changeset id="1" author="Diego.Pacheco">
<createtable tablename="pessoas">
<column name="id" type="int">
<constraints primarykey="true" nullable="false">
</column>
<column name="nome" type="varchar(50)">
<constraints nullable="false">
</column>
<column name="active" type="boolean" defaultvalue="1">
</createtable>
</changeset>
<changeset id="2" author="Crom.God">
<addcolumn tablename="pessoas">
<column name="mitologico" type="boolean">
<constraints nullable="true">
</column>
</addcolumn>
</changeset>
<changeset id="3" author="4Winds.God">
<comment>renomeada a coluna mitologia da tabela pessoas de mitologico para mit.</comment>
<renamecolumn tablename="pessoas" columndatatype="boolean" oldcolumnname="mitologico" newcolumnname="mit">
</changeset>
<changeset author="4" id="Diego.Pacheco">
<sqlfile path="src/main/resources/sql/changelog.sql">
<rollback>
DROP TABLE testSQL;
</rollback>
</changeset>
<changeset author="5" id="Diego.Pacheco">
<sqlfile path="src/main/resources/sql/changelog-proc.sql">
<rollback>
DROP FUNCTION soma(INTEGER, INTEGER);
</rollback>
</changeset>
</databasechangelog>
.png>
Além
do changeset 1 e 2, adicionei o 3, 4 e 5. Perceba que o liquibase não
vai aplicar as mudanças do changeset 1 e 2, por que ele ja sabe que
estas mudanças foram aplicadas na base graças a sua tabela de controle
do banco. Ele ainda tem um controle de checksun para caso algum
espertinho tentar burlar o sistema :).png>
.png>
No changeset 4 e 5 delegam
as mudanças para scripts SQL, isto é fundamental para aplicação e
criação de procedures, triggers, functions e para que DBAs possa rodar
scripts mais apurados para correções e ajustes do banco..png>
.png>
Você
deve etar curioso com as tags de rollback, elas existem por que o
liquibase não consegui fazer rollback automatico para todas os seus
refactorings. nestes casos você pode especificar o mecanismo de
rollback..png>
.png>
Executando o changelog completo no banco com o profile de update $mvn install -P update e passar a tag com $mvn install -P tag vamos ter o seguinte resultado ao refazer a query em databasechangelog..png>

.png>.png>
Perceba
que o comentário passado pelo changeset 3 foi parar na tabela de
controle do liquibase também. Além disso, para propósitos de controle e
documentação, você pode gerar o dbdoc, que é uma espécia de javadoc para
os changelogs aplicados no banco. Eu acossiei isso ao ciclo padrão de
build do maven. Logo, toda vez que você faz um install ele gera a
documentação do banco no diretório target/docs/dbdocs..png>.png>
.png>.png>
Em caso de dúvidas ou compliance.png>.png>
Nestes
casos você pode fazer que o liquibase gera um arquivo .sql com as
mudanças, mas não aplica na base. Esta aplicação fica em um segundo
momento, assim um DBA/AD pode revisar e depois aplicar a mudança por
este arquivo sql ou através do próprio liquibase. Criei um profile no
maven para isto também, basta rodar $mvn install -P updateSQL..png>.png>
.png>.png>
.png>.png>
Controlando diferenças entre bancos de dados.png>.png>
.png>.png>Você
pode controlar as mudanças entre bancos de dado. Por exemplo, do banco
de desenvolvimento com o banco de testes e produção. Para isso eu criei
um profile chamado de diff, ele usa as configurações do banco de dados
padrão e o banco informado no arquivo db.operations.properties.
.png>.png>
Existem
dois tipos de relatórios. O primeiro é chamado de ‘diff’; este modelo é
escrito na saída padrão, em formato texto, para leitura das mudanças. No
formato ‘diffChangeLog’ ele joga no console as diferenças em formato de
changelog. Isto é útil por que você pode salvar este changelog e depois
executar o mesmo na base incompleta..png>.png>
.png>.png>
E os bancos já criados?.png>.png>
.png>.png>
É
possível gerar um engenharia reversa do banco. Para isso você pode usar
o profile que criei no maven chamado de ‘reverse-changelog’, mas essa funcionalidade tem algumas limitações, como por exemplo stored,
procedures, triggers e functions..png>.png>
.png>.png>
Se você tem estes tipos de
objetos, eu recomendo fazer um export do schema do banco em forma sql e
depois criar um changeset do liquibase que importa este aquivo sql
através da tag sqlFile path=”caminhoParaSqldoBanco.sql”..png>.png>
.png>.png>
Eo Rollback?.png>.png>
.png>.png>Ainda
é possível aplicar rollback do banco de dados. Neste caso ele vai fazer
rollback de todo o changelog. Podemos fazer rollback por changelog,
data ou tag por exemplo. Eu prefiro trabalhar sempre com tags.
.png>.png>
Basta usar o meu profile do maven para rollback com o comando $mvn install -P rollback isto vai realizar o rollback para a tag especificada no arquivo de propriedades.png>.png>
.png>.png>
# Configuração para rollback no banco
liquibase.rollback.conf.rollbackTag=1.0
Usei
arquivos de propriedades por que podemos sobreescrever estas
propriedades e se for necessário na hora de rodar podemos mudar estes
valores. Ao executar o cando acima você tera um resultado semelhante ao abaixo:.png>.png>
[INFO] Scanning for projects...
[INFO] ------------------------------------------------------------------------
[INFO] Building liquibase-postgres-maven2
[INFO]
[INFO] Id: com.blogspot.diegopacheco.sandbox.java:liquibase-postgres-maven2:jar:1.0
[INFO] task-segment: [install]
[INFO] ------------------------------------------------------------------------
[INFO] [properties:read-project-properties]
[INFO] [resources:resources]
[INFO] Using default encoding to copy filtered resources.
[INFO] [liquibase:rollback]
[INFO] ------------------------------------------------------------------------
[INFO] Parsing Liquibase Properties File
[INFO] File: src/main/resources/database-conf/db.operations.properties
[INFO] 'liquibase.diff.conf.url' in properties file is not being used by this task.
[INFO] 'liquibase.dbdoc.ouputDir' in properties file is not being used by this task.
[INFO] 'liquibase.diff.conf.usr' in properties file is not being used by this task.
[INFO] 'liquibase.update.sql.conf.migrationSqlOutputFile' in properties file is not being used by this task.
[INFO] 'liquibase.dbdoc.changeLogFile' in properties file is not being used by this task.
[INFO] 'liquibase.diff.conf.pwd' in properties file is not being used by this task.
[INFO] 'liquibase.tag.conf.id' in properties file is not being used by this task.
[INFO] 'liquibase.default.changelog.propertyFile' in properties file is not being used by this task.
[INFO] 'liquibase.rollback.conf.rollbackTag' in properties file is not being used by this task.
[INFO] ------------------------------------------------------------------------
[INFO] Executing on Database: jdbc:postgresql://localhost:5432/liquibase
02/08/2009 22:33:49 liquibase.database.template.JdbcTemplate comment
INFO: Lock Database
02/08/2009 22:33:49 liquibase.lock.LockHandler acquireLock
INFO: Successfully acquired change log lock
02/08/2009 22:33:49 liquibase.database.AbstractDatabase getRanChangeSetList
INFO: Reading from databasechangelog
02/08/2009 22:33:49 liquibase.parser.visitor.RollbackVisitor visit
INFO: Rolling Back Changeset:src/main/resources/changelogs/changelog.xml::Diego.Pacheco::5::(MD5Sum: b3ba926f79bcfe14e815efe642d3dd)
02/08/2009 22:33:49 liquibase.database.template.JdbcTemplate comment
INFO: Rolling Back ChangeSet: src/main/resources/changelogs/changelog.xml::Diego.Pacheco::5::(MD5Sum: b3ba926f79bcfe14e815efe642d3dd)
02/08/2009 22:33:49 liquibase.parser.visitor.RollbackVisitor visit
INFO: Rolling Back Changeset:src/main/resources/changelogs/changelog.xml::Diego.Pacheco::4::(MD5Sum: c9b7b619c169fdcee7741466fdcc4)
02/08/2009 22:33:49 liquibase.database.template.JdbcTemplate comment
INFO: Rolling Back ChangeSet: src/main/resources/changelogs/changelog.xml::Diego.Pacheco::4::(MD5Sum: c9b7b619c169fdcee7741466fdcc4)
02/08/2009 22:33:49 liquibase.parser.visitor.RollbackVisitor visit
INFO: Rolling Back Changeset:src/main/resources/changelogs/changelog.xml::3::4Winds.God::(MD5Sum: 39d1b5b66c1b379c4d2fef7168b9f)
02/08/2009 22:33:49 liquibase.database.template.JdbcTemplate comment
INFO: Rolling Back ChangeSet: src/main/resources/changelogs/changelog.xml::3::4Winds.God::(MD5Sum: 39d1b5b66c1b379c4d2fef7168b9f)
02/08/2009 22:33:49 liquibase.database.template.JdbcTemplate comment
INFO: Release Database Lock
02/08/2009 22:33:49 liquibase.lock.LockHandler releaseLock
INFO: Successfully released change log lock
02/08/2009 22:33:49 liquibase.database.template.JdbcTemplate comment
INFO: Release Database Lock
02/08/2009 22:33:49 liquibase.lock.LockHandler releaseLock
INFO: Successfully released change log lock
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] [compiler:compile]
[INFO] No sources to compile
[INFO] [resources:testResources]
[INFO] Using default encoding to copy filtered resources.
[INFO] [compiler:testCompile]
[INFO] No sources to compile
[INFO] [surefire:test]
[INFO] No tests to run.
[INFO] [jar:jar]
[INFO] [exec:java]
[INFO] [install:install]
[INFO] Installing D:\Diego\Java\bin\workspaces-eclipse\eclipse_workspace\liquibase-postgres-maven2\target\liquibase-postgres-maven2-1.0.jar to C:\Users\Diego Pacheco\.m2\repository\com\blogspot\diegopacheco\sandbox\java\liquibase-postgres-maven2\1.0\liquibase-postgres-maven2-1.0.jar
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 4 seconds
[INFO] Finished at: Sun Aug 02 22:33:51 BRT 2009
[INFO] Final Memory: 3M/11M
[INFO] ------------------------------------------------------------------------.png>.png>
.png>.png>
.png>.png>
Isto vai deixar o banco somente com o os
changesets 1 e 2 que foram definidos na primeira tag da versão 1.0. O
liquibase permite a aplicação incremental das mudanças de forma muito
fácil e ainda com suporte a rollback..png>.png>
.png>.png>
Confira os arquivos de propriedades completos abaixo:.png>.png>
.png>.png>
db.properties.png>.png>
# ----------------------------------------------------------------
#
# Neste arquivo estão as configurações acesso ao banco de dados.
#
# @autor Diego Pacheco
# @version 1.0
# @since 02/08/2009
#
# ----------------------------------------------------------------
# Postgres 8.4
liquibase.driver=org.postgresql.Driver
liquibase.url=jdbc:postgresql://localhost:5432/liquibase
liquibase.username=m2liquibase
liquibase.password=m2liquibase.png>.png>
.png>.png>
db.operations.properties.png>.png>
# ----------------------------------------------------------------
#
# Neste arquivo estão as configurações de Tag, Rollback e DIFF.
#
# @autor Diego Pacheco
# @version 1.0
# @since 02/08/2009
#
# ----------------------------------------------------------------
#Configurações gerais para todas as tasks e mojos
liquibase.dbdoc.changeLogFile=src/main/resources/changelogs/changelog.xml
liquibase.default.changelog.propertyFile=src/main/resources/database-conf/db.operations.properties
# Configuração para rollback no banco
liquibase.rollback.conf.rollbackTag=1.0
# Configuração para tag no banco
liquibase.tag.conf.id=1.0
# Configurações para o updateSQL
liquibase.update.sql.conf.migrationSqlOutputFile=/target/liquibase-db-sql.sql
# Configurações para DocDB
liquibase.dbdoc.ouputDir=target/docs/dbdoc
# Configurações para DIFF de bancos
# Postgres 8.4
liquibase.diff.conf.url=jdbc:postgresql://localhost:5432/liquibasediff
liquibase.diff.conf.usr=m2liquibasediff
liquibase.diff.conf.pwd=m2liquibasediff.png>.png>
pom.xml.png>.png>
<project xmlns="http://maven.apache.org/POM/4.0.0" xsi="http://www.w3.org/2001/XMLSchema-instance" schemalocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelversion>4.0.0</modelversion>
<groupid>com.blogspot.diegopacheco.sandbox.java</groupid>
<artifactid>liquibase-postgres-maven2</artifactid>
<name>liquibase-postgres-maven2</name>
<version>1.0</version>
<description>liquibase-postgres-maven2</description>
<packaging>jar</packaging>
<reporting>
<plugins>
<plugin>
<groupid>org.apache.maven.plugins</groupid>
<artifactid>maven-project-info-reports-plugin</artifactid>
<version>2.0.1</version>
</plugin>
<plugin>
<groupid>org.apache.maven.plugins</groupid>
<artifactid>maven-surefire-report-plugin</artifactid>
<version>2.4.2</version>
</plugin>
</plugins>
</reporting>
<build>
<plugins>
<plugin>
<groupid>org.codehaus.mojo</groupid>
<artifactid>properties-maven-plugin</artifactid>
<version>1.0-alpha-1</version>
<executions>
<execution>
<phase>initialize</phase>
<goals>
<goal>read-project-properties</goal>
</goals>
<configuration>
<files>
<file>${basedir}/src/main/resources/database-conf/db.properties</file>
<file>${basedir}/src/main/resources/database-conf/db.operations.properties</file>
</files>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupid>org.codehaus.mojo</groupid>
<artifactid>exec-maven-plugin</artifactid>
<version>1.0.2</version>
<executions>
<execution>
<phase>integration-test</phase>
<goals>
<goal>java</goal>
</goals>
</execution>
</executions>
<configuration>
<mainclass>liquibase.commandline.Main</mainclass>
<arguments>
<argument>--driver=${liquibase.driver}</argument>
<argument>--url=${liquibase.url}</argument>
<argument>--username=${liquibase.username}</argument>
<argument>--password=${liquibase.password}</argument>
<argument>--changeLogFile=${liquibase.dbdoc.changeLogFile}</argument>
<argument>dbDoc</argument>
<argument>${liquibase.dbdoc.ouputDir}</argument>
</arguments>
</configuration>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>updateSQL</id>
<build>
<plugins>
<plugin>
<groupid>org.liquibase</groupid>
<artifactid>liquibase-plugin</artifactid>
<version>1.9.3.0</version>
<executions>
<execution>
<phase>process-resources</phase>
<configuration>
<propertyfile>${liquibase.default.changelog.propertyFile}</propertyfile>
<migrationsqloutputfile>${liquibase.update.sql.conf.migrationSqlOutputFile}</migrationsqloutputfile>
<changelogfile>${liquibase.dbdoc.changeLogFile}</changelogfile>
<promptonnonlocaldatabase>false</promptonnonlocaldatabase>
</configuration>
<goals>
<goal>updateSQL</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>update</id>
<build>
<plugins>
<plugin>
<groupid>org.liquibase</groupid>
<artifactid>liquibase-plugin</artifactid>
<version>1.9.3.0</version>
<executions>
<execution>
<phase>process-resources</phase>
<configuration>
<propertyfile>${liquibase.default.changelog.propertyFile}</propertyfile>
<changelogfile>${liquibase.dbdoc.changeLogFile}</changelogfile>
<promptonnonlocaldatabase>false</promptonnonlocaldatabase>
</configuration>
<goals>
<goal>update</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>tag</id>
<build>
<plugins>
<plugin>
<groupid>org.liquibase</groupid>
<artifactid>liquibase-plugin</artifactid>
<version>1.6.1.0</version>
<executions>
<execution>
<phase>process-resources</phase>
<configuration>
<propertyfile>${liquibase.default.changelog.propertyFile}</propertyfile>
<tag>${liquibase.tag.conf.id}</tag>
<promptonnonlocaldatabase>false</promptonnonlocaldatabase>
</configuration>
<goals>
<goal>tag</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>rollback</id>
<build>
<plugins>
<plugin>
<groupid>org.liquibase</groupid>
<artifactid>liquibase-plugin</artifactid>
<version>1.9.3.0</version>
<executions>
<execution>
<phase>process-resources</phase>
<configuration>
<propertyfile>${liquibase.default.changelog.propertyFile}</propertyfile>
<changelogfile>${liquibase.dbdoc.changeLogFile}</changelogfile>
<rollbacktag>${liquibase.rollback.conf.rollbackTag}</rollbacktag>
</configuration>
<goals>
<goal>rollback</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>reverse-changelog</id>
<build>
<plugins>
<plugin>
<groupid>org.codehaus.mojo</groupid>
<artifactid>exec-maven-plugin</artifactid>
<version>1.0.2</version>
<executions>
<execution>
<goals>
<goal>java</goal>
</goals>
</execution>
</executions>
<configuration>
<mainclass>liquibase.commandline.Main</mainclass>
<arguments>
<argument>--driver=${liquibase.driver}</argument>
<argument>--url=${liquibase.url}</argument>
<argument>--username=${liquibase.username}</argument>
<argument>--password=${liquibase.password}</argument>
<argument>generateChangeLog</argument>
</arguments>
</configuration>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>diff</id>
<build>
<plugins>
<plugin>
<groupid>org.codehaus.mojo</groupid>
<artifactid>exec-maven-plugin</artifactid>
<version>1.0.2</version>
<executions>
<execution>
<goals>
<goal>java</goal>
</goals>
</execution>
</executions>
<configuration>
<mainclass>liquibase.commandline.Main</mainclass>
<arguments>
<argument>--driver=${liquibase.driver}</argument>
<argument>--url=${liquibase.url}</argument>
<argument>--username=${liquibase.username}</argument>
<argument>--password=${liquibase.password}</argument>
<argument>diffChangeLog</argument>
<argument>--baseUrl=${liquibase.diff.conf.url}</argument>
<argument>--baseUsername=${liquibase.diff.conf.usr}</argument>
<argument>--basePassword=${liquibase.diff.conf.pwd}</argument>
</arguments>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
<dependencies>
<dependency>
<groupid>postgresql</groupid>
<artifactid>postgresql</artifactid>
<version>8.3-603.jdbc4</version>
</dependency>
<dependency>
<groupid>org.codehaus.mojo</groupid>
<artifactid>exec-maven-plugin</artifactid>
<version>1.0.2</version>
</dependency>
<dependency>
<groupid>org.liquibase</groupid>
<artifactid>liquibase-plugin</artifactid>
<version>1.9.3.0</version>
</dependency>
<dependency>
<groupid>org.codehaus.mojo</groupid>
<artifactid>properties-maven-plugin
</artifactid>
<version>1.0-alpha-1</version>
</dependency>
</dependencies>
</project>.png>.png>
.png>.png>
Conclusão.png>.png>
.png>.png>
O
Liquibase é uma excelente ferramenta para aplicação de refactoring de
banco de dados, assim como controle de mudanças e gerência de
configuração do banco, claro que sempre aliada a uma ferramenta de SCM
como o CVS ou Subversion..png>.png>
.png>.png>
A ferramenta ainda não tem um bom IDE
gráfico, que é o maior fator que impede a sua adoção em escala global. Mas acredito que isso venha com o tempo. Esta ferramenta permite
realizar as mudanças e versionar as mesmas através do Subersion e o
Maven para execução em um servidor de build continuo..png>.png>
.png>.png>
Para
fechar, só falta aplicar testes unitários de banco de dados, assim você
fazo refactoring e aplica com o liquibase e depois roda os testes e
tudo funcionar você verciona no subversion e avisa aos envolvidos no
projeto..png>.png>
.png>.png>
A questão dos testes é fundamental e está diretamente
ligada com a do refactoring de banco de dados, este assunto irei
abordar nos próximos posts. Se você quiser pode obter os fontes
completos desta aplicação que fiz no meu repositório do subversion..png>.png>
.png>.png>
Abraços e até a próxima..png>.png>
1 Comentário
Qual a sua opinião?