Refactoring de Banco de Dados com Liquibase: Parte 2 Liquibase e Maven 2
No post anterior comentei sobre a importância das práticas da engenharia como refactoring e versionamento aplicados ao Banco de Dados. Neste post vou mostrar 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 é você pode colocar este projeto no seu servidor de build continuo e 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 a estrutura do projeto que criei:
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 e 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 e 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 isto facilita o uso de XML.
O ideal seria utilizar um IDE gráfico, neste momento existe um IDE que é baseado em eclipse porem a solução esta parada(02/08/2009), logo vamos ter que lidar com o XML, porem existem outras formas de informar mudanças para o banco e vou mostrar isto mais a frente. Então vamos ver um changelog com alguns changesets.
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 por que 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 isto 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 por que 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:
Uma vez este script 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:
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:
Você ira 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.
Depois de passar a tag se refizermos a query na tabela databasechangelog vamos obter o seguinte resultado:
Como você pode perceber a ultima mudança ficou com a tag 1.0. Assim o Liquibase aplica a tag sempre na ultima modificação, logo se você tivesse aplicado 100 mudanças as 100 fariam parte desta tag. Isso é fundamental para a gerência de configurações e para os procedimentos de rollback.
Vamos aplicar mais mudanças no banco de dados e depois passar a tag para versão 2.0. Confira o changelog a baixo:
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 :)
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.
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.
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.
Perceba que o comentário passado pelo changeset 3 foi parar na tabela de controle do liquibase também. Além disso para propositos 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.
Em Casos de dúvida ou Compliance...
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ço 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.
Controlando Diferenças entre bancos de dados...
Você pode controlar as mudanças entre bancos de dados 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 confogurações do banco de dados padrão e o banco informado no arquivo db.operations.properties.
Existem dois tipos de relatórios o primeiro é chamado de 'diff' neste modelo é escrito na saida padrão em formato texto para leitura as 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.
E os bancos ja criados?
É possível gerar um engenharia reversa do banco, para isso você pode usar o profile que criei no maven chamado de 'reverse-changelog' porem esta funcionalidade tem algumas limitações como por exemplo stored, procedures, triggers e functions.
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".
e o Rollback ?
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.
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
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 de baixo:
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.
Configra os arquivos de propriedades completos a baixo:
db.properties
db.operations.properties
pom.xml
Conclusão
O Liquibase é uma exelente 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.
A ferramenta ainda não tem um bom IDE gráfico que é o maior fator que impete 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.
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.
A questão dos testes é fundamental e esta 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.
Abraços e até a próxima.
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 é você pode colocar este projeto no seu servidor de build continuo e 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 a 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
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 e 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 e 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 isto facilita o uso de XML.
O ideal seria utilizar um IDE gráfico, neste momento existe um IDE que é baseado em eclipse porem a solução esta parada(02/08/2009), logo vamos ter que lidar com o XML, porem existem outras formas de informar mudanças para o banco e vou mostrar isto mais a frente. Então vamos ver um changelog com alguns changesets.
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 por que 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 isto 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 por que 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 este script 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ê ira 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 ultima mudança ficou com a tag 1.0. Assim o Liquibase aplica a tag sempre na ultima modificação, logo se você tivesse aplicado 100 mudanças as 100 fariam parte desta tag. Isso é fundamental para a gerência de configurações e para os procedimentos de rollback.
Vamos aplicar mais mudanças no banco de dados e depois passar a tag para versão 2.0. Confira o changelog a baixo:
renomeada a coluna mitologia da tabela pessoas de mitologico para mit. DROP TABLE testSQL; DROP FUNCTION soma(INTEGER, INTEGER);
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 :)
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.
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.
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.
Perceba que o comentário passado pelo changeset 3 foi parar na tabela de controle do liquibase também. Além disso para propositos 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.
Em Casos de dúvida ou Compliance...
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ço 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.
Controlando Diferenças entre bancos de dados...
Você pode controlar as mudanças entre bancos de dados 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 confogurações do banco de dados padrão e o banco informado no arquivo db.operations.properties.
Existem dois tipos de relatórios o primeiro é chamado de 'diff' neste modelo é escrito na saida padrão em formato texto para leitura as 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.
E os bancos ja criados?
É possível gerar um engenharia reversa do banco, para isso você pode usar o profile que criei no maven chamado de 'reverse-changelog' porem esta funcionalidade tem algumas limitações como por exemplo stored, procedures, triggers e functions.
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".
e o Rollback ?
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.
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
# 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 de baixo:
[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] ------------------------------------------------------------------------
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.
Configra os arquivos de propriedades completos a baixo:
db.properties
# ---------------------------------------------------------------- # # 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
db.operations.properties
# ---------------------------------------------------------------- # # 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
pom.xml
4.0.0 com.blogspot.diegopacheco.sandbox.java liquibase-postgres-maven2 liquibase-postgres-maven2 1.0 liquibase-postgres-maven2 jar org.apache.maven.plugins maven-project-info-reports-plugin 2.0.1 org.apache.maven.plugins maven-surefire-report-plugin 2.4.2 org.codehaus.mojo properties-maven-plugin 1.0-alpha-1 initialize read-project-properties ${basedir}/src/main/resources/database-conf/db.properties ${basedir}/src/main/resources/database-conf/db.operations.properties org.codehaus.mojo exec-maven-plugin 1.0.2 integration-test java liquibase.commandline.Main --driver=${liquibase.driver} --url=${liquibase.url} --username=${liquibase.username} --password=${liquibase.password} --changeLogFile=${liquibase.dbdoc.changeLogFile} dbDoc ${liquibase.dbdoc.ouputDir} updateSQL org.liquibase liquibase-plugin 1.9.3.0 process-resources ${liquibase.default.changelog.propertyFile} ${liquibase.update.sql.conf.migrationSqlOutputFile} ${liquibase.dbdoc.changeLogFile} false updateSQL update org.liquibase liquibase-plugin 1.9.3.0 process-resources ${liquibase.default.changelog.propertyFile} ${liquibase.dbdoc.changeLogFile} false update tag org.liquibase liquibase-plugin 1.6.1.0 process-resources ${liquibase.default.changelog.propertyFile} ${liquibase.tag.conf.id} false tag rollback org.liquibase liquibase-plugin 1.9.3.0 process-resources ${liquibase.default.changelog.propertyFile} ${liquibase.dbdoc.changeLogFile} ${liquibase.rollback.conf.rollbackTag} rollback reverse-changelog org.codehaus.mojo exec-maven-plugin 1.0.2 java liquibase.commandline.Main --driver=${liquibase.driver} --url=${liquibase.url} --username=${liquibase.username} --password=${liquibase.password} generateChangeLog diff org.codehaus.mojo exec-maven-plugin 1.0.2 java liquibase.commandline.Main --driver=${liquibase.driver} --url=${liquibase.url} --username=${liquibase.username} --password=${liquibase.password} diffChangeLog --baseUrl=${liquibase.diff.conf.url} --baseUsername=${liquibase.diff.conf.usr} --basePassword=${liquibase.diff.conf.pwd} postgresql postgresql 8.3-603.jdbc4 org.codehaus.mojo exec-maven-plugin 1.0.2 org.liquibase liquibase-plugin 1.9.3.0 org.codehaus.mojo properties-maven-plugin 1.0-alpha-1
Conclusão
O Liquibase é uma exelente 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.
A ferramenta ainda não tem um bom IDE gráfico que é o maior fator que impete 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.
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.
A questão dos testes é fundamental e esta 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.
Abraços e até a próxima.