(转)在Web项目中使用LiquiBase实现数据库自动更新

来源:互联网 发布:国外js特效网站 开源 编辑:程序博客网 时间:2024/05/16 06:41

在Web项目中,我们可以通过配置servlet listener使用LiquiBase自动更新数据库。需要以下七个步骤:
1. 创建一个数据库变更日志(change log)文件。
2. 在变更日志文件内部创建一个变更集(change set)。
3. 配置JNDI数据源。
4. 在项目中加入包liquibase。
5. 配置项目中的web.xml文件。
6. 启动项目。
7. 检验数据库中的变更。


Changelog.xml:


Html代码  收藏代码

   
Java代码 复制代码 收藏代码
  1. <?xml version="1.0" encoding="UTF-8"?>     
  2.     <databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog/1.9"     
  3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"     
  4.     xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog/1.9    
  5.             http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-1.9.xsd">    
  6.     <changeSet id="1" author="jim">     
  7.          
  8.     <createTable tableName="useraccount">     
  9.     <column name="userid" type="bigint(20)">     
  10.     <constraints primaryKey="true" />     
  11.     </column>     
  12.     <column name="accountstate" type="varchar(255)" />     
  13.     <column name="expiredDate" type="datetime" />     
  14.     <column name="username" type="varchar(255)" />     
  15.     </createTable>     
  16.          
  17.     <addUniqueConstraint tableName="useraccount"     
  18.     columnNames="username" constraintName="username" />     
  19.          
  20.     </changeSet>     
  21.          
  22.     <changeSet id="2" author="jim">     
  23.          
  24.     <addColumn tableName="useraccount">     
  25.     <column name="gender" type="varchar(1)" value="M">     
  26.     <constraints nullable="false"/>     
  27.     </column>     
  28.     </addColumn>     
  29.                  
  30.     </changeSet>     
  31.          
  32.     </databaseChangeLog>    
[java] view plain copy print?
  1. <?xml version="1.0" encoding="UTF-8"?>    
  2.     <databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog/1.9"    
  3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    
  4.     xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog/1.9    
  5.             http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-1.9.xsd">    
  6.     <changeSet id="1" author="jim">    
  7.         
  8.     <createTable tableName="useraccount">    
  9.     <column name="userid" type="bigint(20)">    
  10.     <constraints primaryKey="true" />    
  11.     </column>    
  12.     <column name="accountstate" type="varchar(255)" />    
  13.     <column name="expiredDate" type="datetime" />    
  14.     <column name="username" type="varchar(255)" />    
  15.     </createTable>    
  16.         
  17.     <addUniqueConstraint tableName="useraccount"    
  18.     columnNames="username" constraintName="username" />    
  19.         
  20.     </changeSet>    
  21.         
  22.     <changeSet id="2" author="jim">    
  23.         
  24.     <addColumn tableName="useraccount">    
  25.     <column name="gender" type="varchar(1)" value="M">    
  26.     <constraints nullable="false"/>    
  27.     </column>    
  28.     </addColumn>    
  29.                 
  30.     </changeSet>    
  31.         
  32.     </databaseChangeLog>    




Web.xml:
Html代码  收藏代码

   
Java代码 复制代码 收藏代码
  1. <?xml version="1.0" encoding="UTF-8"?>     
  2.     <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"     
  3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"     
  4.     xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">     
  5.     <display-name>liquid</display-name>     
  6.          
  7.     <description>MySQL Test App</description>     
  8.     <resource-ref>     
  9.     <description>DB Connection</description>     
  10.     <res-ref-name>jdbc/test</res-ref-name>     
  11.     <res-type>javax.sql.DataSource</res-type>     
  12.     <res-auth>Container</res-auth>     
  13.     </resource-ref>     
  14.          
  15.     <context-param>     
  16.     <param-name>LIQUIBASE_CHANGELOG</param-name>     
  17.     <param-value>db.changelog.xml</param-value>     
  18.     </context-param>     
  19.          
  20.     <context-param>     
  21.     <param-name>LIQUIBASE_DATA_SOURCE</param-name>     
  22.     <param-value>java:comp/env/jdbc/test</param-value>     
  23.     </context-param>     
  24.          
  25.     <context-param>     
  26.     <param-name>LIQUIBASE_FAIL_ON_ERROR</param-name>     
  27.     <param-value>true</param-value>     
  28.     </context-param>     
  29.          
  30.     <context-param>     
  31.     <param-name>LIQUIBASE_CONTEXTS</param-name>     
  32.     <param-value>jdbc/test</param-value>     
  33.     </context-param>     
  34.          
  35.     <listener>     
  36.     <listener-class>liquibase.servlet.LiquibaseServletListener</listener-class>     
  37.     </listener>     
  38.          
  39.     </web-app>    
[java] view plain copy print?
  1. <?xml version="1.0" encoding="UTF-8"?>    
  2.     <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"    
  3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    
  4.     xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">    
  5.     <display-name>liquid</display-name>    
  6.         
  7.     <description>MySQL Test App</description>    
  8.     <resource-ref>    
  9.     <description>DB Connection</description>    
  10.     <res-ref-name>jdbc/test</res-ref-name>    
  11.     <res-type>javax.sql.DataSource</res-type>    
  12.     <res-auth>Container</res-auth>    
  13.     </resource-ref>    
  14.         
  15.     <context-param>    
  16.     <param-name>LIQUIBASE_CHANGELOG</param-name>    
  17.     <param-value>db.changelog.xml</param-value>    
  18.     </context-param>    
  19.         
  20.     <context-param>    
  21.     <param-name>LIQUIBASE_DATA_SOURCE</param-name>    
  22.     <param-value>java:comp/env/jdbc/test</param-value>    
  23.     </context-param>    
  24.         
  25.     <context-param>    
  26.     <param-name>LIQUIBASE_FAIL_ON_ERROR</param-name>    
  27.     <param-value>true</param-value>    
  28.     </context-param>    
  29.         
  30.     <context-param>    
  31.     <param-name>LIQUIBASE_CONTEXTS</param-name>    
  32.     <param-value>jdbc/test</param-value>    
  33.     </context-param>    
  34.         
  35.     <listener>    
  36.     <listener-class>liquibase.servlet.LiquibaseServletListener</listener-class>    
  37.     </listener>    
  38.         
  39.     </web-app>    



     通过上面的web.xml文件,可以看到这里配置了一个listener,LiquibaseServletListener这个类继承了ServletContextListener,ServletContextListener 是 ServletContext 的监听者,如果 ServletContext 发生变化,如服务器启动时 ServletContext 被创建,服务器关闭时 ServletContext 将要被销毁。当服务器启动时,LiquibaseServletListener的 contextInitialized()方法被调用,这个方法会比较数据库与Changelog.xml的不同,并自动更新数据库。
     那么LiquiBase是怎么更新数据的呢?当LiquibaseServletListener第一次被调用时,会创建了两个特定的表。第一个特定于 LiquiBase 的表称为 databasechangelog,它跟踪应用到数据库的所有变更 — 有助于跟踪谁执行了数据库变更以及原因。第二个特定于 LiquiBase的表是 databasechangelock,标识出具有数据库变更锁的用户。LiquiBase通过比较databasechangelog中的记录和Changelog.xml中的changeSet,更新数据库。
     liquid项目1中Changelog.xml中的只有1条changeset

Xml代码  收藏代码

   
Java代码 复制代码 收藏代码
  1. <changeSet id="1" author="jim">     
  2.          
  3.     <createTable tableName="useraccount">     
  4.     <column name="userid" type="bigint(20)">     
  5.     <constraints primaryKey="true" />     
  6.     </column>     
  7.     <column name="accountstate" type="varchar(255)" />     
  8.     <column name="expiredDate" type="datetime" />     
  9.     <column name="username" type="varchar(255)" />     
  10.     </createTable>     
  11.          
  12.     <addUniqueConstraint tableName="useraccount"     
  13.     columnNames="username" constraintName="username" />     
  14.          
  15.     </changeSet>    
[java] view plain copy print?
  1. <changeSet id="1" author="jim">    
  2.         
  3.     <createTable tableName="useraccount">    
  4.     <column name="userid" type="bigint(20)">    
  5.     <constraints primaryKey="true" />    
  6.     </column>    
  7.     <column name="accountstate" type="varchar(255)" />    
  8.     <column name="expiredDate" type="datetime" />    
  9.     <column name="username" type="varchar(255)" />    
  10.     </createTable>    
  11.         
  12.     <addUniqueConstraint tableName="useraccount"    
  13.     columnNames="username" constraintName="username" />    
  14.         
  15.     </changeSet>    



    启动项目1,LiquiBase会自动创建表useraccount,并添加字段userid,accountstate,expiredDate,username。Databasechangelog表会新增一条表示<changeSet id="1" author="jim">的记录。

    liquid项目2中Changelog.xml中的多加了1条changeset


Xml代码  收藏代码

   
Java代码 复制代码 收藏代码
  1. <changeSet id="2" author="jim">     
  2.          
  3.     <addColumn tableName="useraccount">     
  4.     <column name="gender" type="varchar(1)" value="M">     
  5.     <constraints nullable="false"/>     
  6.     </column>     
  7.     </addColumn>     
  8.                  
  9.     </changeSet>    
[java] view plain copy print?
  1. <changeSet id="2" author="jim">    
  2.         
  3.     <addColumn tableName="useraccount">    
  4.     <column name="gender" type="varchar(1)" value="M">    
  5.     <constraints nullable="false"/>    
  6.     </column>    
  7.     </addColumn>    
  8.                 
  9.     </changeSet>    




     启动项目2,LiquiBase会发现<changeSet id="1" author="jim">已经更新,所以只更新新增的<changeSet id="2" author="jim">。添加字段gender,并设置值为“M”。如果删除表useraccount,并删除表Databasechangelog中所有的记录,重新启动项目2,LiquiBase将创建表useraccount,并添加字段userid,accountstate,expiredDate,username和gender,并设置gender的值为“M”。
    根据上面LiquiBase的特性,如果我们把每一次的数据库变更都写进到changeSet,并使用LiquiBase更新数据库,我们就可以通过对Changelog.xml文件进行版本控制,来控制数据库的版本。当我们升级软件的时候,也可以很方便地自动更新数据库。

  

    参考资料:
    IBM 使用 LiquiBase 管理数据库变更:http://www.ibm.com/developerworks/cn/java/j-ap08058/index.html

    LiquiBase官网:http://www.liquibase.org/ (国内的IP可能进不去,要用代理)
阅读全文
0 0