zoukankan      html  css  js  c++  java
  • Liquibase

    LiquiBase是一个用于数据库重构和迁移的开源工具,通过日志文件的形式记录数据库的变更,然后执行日志文件中的修改,将数据库更新或回滚到一致的状态。LiquiBase的主要特点有:

    • 支持几乎所有主流的数据库,如MySQL, PostgreSQL, Oracle, Sql Server, DB2等;
    • 支持多开发者的协作维护;
    • 日志文件支持多种格式,如XML, YAML, JSON, SQL等;
    • 支持多种运行方式,如命令行、Spring集成、Maven插件、Gradle插件等;

    changelog文件格式

    changelog是LiquiBase用来记录数据库的变更,一般放在CLASSPATH下,然后配置到执行路径中。
    changelog支持多种格式,主要有XML/JSON/YAML/SQL,其中XML/JSON/YAML除了具体格式语法不同,节点配置很类似,SQL格式中主要记录SQL语句,这里仅给出XML格式和SQL格式的示例,更多的格式示例请参考文档

    changelog.xml

    <changeSet author="admin" id="1496901181769-1">
        <createTable schemaName="ihome" tableName="test">
            <column autoIncrement="true" name="id" type="INT">
                <constraints primaryKey="true"/>
            </column>
            <column name="name" type="VARCHAR(10)"/>
        </createTable>
    </changeSet>

    changelog.sql

    --liquibase formatted sql
    --changeset daniel:16040707
    CREATE TABLE `role_authority_sum` (
      `row_id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增id',
      `role_id` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '关联role的role_id',
      `authority_sum` int(11) unsigned NOT NULL DEFAULT '0' COMMENT 'perms的值的和',
      `data_type_id` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '关联data_type的id',
      PRIMARY KEY (`row_id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='角色的权限值的和,如角色有RD权限,则和为2+8=10';

    在执行changelog的时候,会在数据库记录执行记录,主要用了下面的两张表:

    1. databasechangelog
    2. databasechangeloglock

    常用的标签及命令

    1. 标签

    一个<changeSet>标签对应一个变更集,由属性id、name,以及changelog的文件路径唯一标识。changelog在执行的时候并不是按照id的顺序,而是按照changeSet在changelog中出现的顺序。

    changelog中的一个changeSet对应一个事务,在changeSet执行完后commit,如果出现错误则rollback。

    2. <include>与<includeAll>标签

    <include>的file属性表示要包含的changelog文件的路径,这个文件可以是LiquiBase支持的任意格式,relativeToChangelogFile如果为true,则表示file属性表示的文件路径是相对于根changelog而不是CLASSPATH的,默认为false。
    <includeAll>指定的是changelog的目录,而不是为文件,如:

    <includeAll path="com/example/changelogs/"/>

    注意: 目前<include>没有解决重复引用和循环引用的问题,重复引用还好,LiquiBase在执行的时候可以判断重复,而循环引用会导致无限循环,需要注意!

    3. 生成已有数据库的changelog

    有两种方式,一种是使用数据库工具导出SQL数据,然后changelog文件以SQL格式记录即可;另一种方式就是用generateChangeLog命令,如:

    liquibase --driver=com.mysql.jdbc.Driver 
          --classpath=./mysql-connector-java-5.1.29.jar 
          --changeLogFile=liquibase/db.changelog.xml 
          --url="jdbc:mysql://127.0.0.1:3306/test" 
          --username=root 
          --password=yourpass 
          generateChangeLog

    不过generateChangeLog不支持以下功能:存储过程、函数以及触发器;

     

    生成文件的路径可以设置:

    <plugin>
        <groupId>org.liquibase</groupId>
        <artifactId>liquibase-maven-plugin</artifactId>
        <version>3.4.2</version>
        <configuration>
            <propertyFile>src/main/resources/liquibase.properties</propertyFile>
            <propertyFileWillOverride>true</propertyFileWillOverride>
            <!--生成文件的路径-->
            <outputChangeLogFile>src/main/resources/changelog_dev.xml</outputChangeLogFile>
        </configuration>
    </plugin>

    也可以配置在properties文件中:

    changeLogFile=src/main/resources/db/changelog/db.changelog-master.xml
    driver=com.mysql.jdbc.Driver
    url=jdbc:mysql://localhost:3306/test?characterEncoding=UTF-8&useSSL=false&jdbcCompliantTruncation=false
    username=root
    password=123456
    verbose=true
    ## 生成文件的路径
    outputChangeLogFile=src/main/resources/changelog_dev.xml

    Maven集成

    liquibase-maven-plugin的配置

    如果需要在父项目中配置子项目共享的LiquiBase配置,而各个子项目可以定义自己的配置,并覆盖父项目中的配置,则只需要在父项目的pom中将propertyFileWillOverride设置为true即可,如:

    <plugin>
        <groupId>org.liquibase</groupId>
        <artifactId>liquibase-maven-plugin</artifactId>
        <version>3.4.2</version>
        <configuration>
            <propertyFileWillOverride>true</propertyFileWillOverride>
            <propertyFile>src/main/resources/liquibase.properties</propertyFile>
        </configuration>
    </plugin>
    ## 执行changelog中的变更
    liquibase:update

    ## rollback
    liquibase:rollback

    rollback有3中形式,分别是:
    - rollbackCount: 表示rollback的changeset的个数;
    - rollbackDate:表示rollback到指定的日期;
    - rollbackTag:表示rollback到指定的tag,需要使用LiquiBase在具体的时间点打上tag;

    liquibase:rollback -Dliquibase.rollbackCount=3

    rollbackDate需要注意日期的格式,必须匹配当前平台上执行DateFormat.getDateInstance()得到的格式,比如我的格式为MMM d, yyyy,示例如:
    liquibase:rollback -Dliquibase.rollbackDate="Apr 10, 2016"

    rollbackTag使用tag标识,所以需要先打tag,示例如:
    liquibase:tag -Dliquibase.tag=tag20160410

    然后rollback到tag20160410,如:
    liquibase:rollback -Dliquibase.rollbackTag=tag20160410

    最佳实践

    1. 如何管理changeLogs

    按照主要的release版本号管理你的changeLogs

    com
      example
        db
          changelog
            db.changelog-master.xml
            db.changelog-1.0.xml
            db.changelog-1.1.xml
            db.changelog-2.0.xml
          DatabasePool.java
          AbstractDAO.java

    db.changelog-master.xml

    该文件包含了所有的release版本的changeLog,并按照正确的顺序引入进来:

    <?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-3.1.xsd">
    
      <include file="com/example/db/changelog/db.changelog-1.0.xml"/> 
      <include file="com/example/db/changelog/db.changelog-1.1.xml"/> 
      <include file="com/example/db/changelog/db.changelog-2.0.xml"/> 
    </databaseChangeLog> 

    2. Managing Stored Procedures
    Try to maintain separate changelog for Stored Procedures and use runOnChange=”true”. This flag forces LiquiBase to check if the changeset was modified. If so, liquibase executes the change again.

    3. One Change per ChangeSet
    As far as possible, Avoid multiple changes per changeset to avoid failed autocommit statements that can leave the database in an unexpected state

    4. ChangeSet Ids
    Choose what works for you. Some use a sequence number starting from 1 and unique within the changelog, some choose a descriptive name (e.g. ‘new-address-table’).

    5. Document ChangeSets
    Use <comments> in the change sets. They say “A stitch in time saves nine!”

    6. Always think about rollback
    Try to write changesets in a way that they can be rolled back. e.g. use relevant change clause instead of using custom <sql> tag. Include a <rollback> clause whenever a change doesn’t support out of box rollback. (e.g. <sql>, <insert>, etc)

    7. Reference Data Management
    Leverage Liquibase to manage your Reference Data. Environment separation (DEV, QA, PROD) can be achieved using “context”. 

    8. Procedure for the developer

    • Using your favorite IDE or editor, create a new local changeSet containing the change;
    • Run Liquibase to execute the new changeSet (this tests the SQL code);
    • Perform the corresponding changes in the application code (e.g., Java code);
    • Test the new application code together with the database change;
    • Commit both the changeSet and the application code.

    问题

    'changeLogFile' in properties file is not being used by this task.

     

     

    链接

  • 相关阅读:
    《UNIX环境高级编程》笔记--UNIX标准化及实现
    SPOJ1811最长公共子串问题(后缀自动机)
    一个leetcode解题报告类目,代码很简洁
    字符压缩题目
    求最佳会议地点
    实现树的横向指针
    lower_bound与upper_bound
    求到所有房子距离和最小的新房子
    增加限制条件的矩阵求和
    切分数组来得到一定的和
  • 原文地址:https://www.cnblogs.com/tonyq/p/8039770.html
Copyright © 2011-2022 走看看