Liquibase常用操作

概述

Liquibase是一个用于数据库重构和迁移的开源工具,通过日志文件的形式记录数据库的变更,然后执行日志文件中的修改,将数据库更新或回滚到一致的状态。它的目标是提供一种数据库类型无关的解决方案,通过执行schema类型的文件来达到迁移。其优点主要有以下:

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

理解databasechangelog和databasechangeloglock表

LiquiBase在执行changelog时,会在数据库中插入两张表:DATABASECHANGELOGDATABASECHANGELOGLOCK,分别记录changelog的执行日志和锁日志。

LiquiBase在执行changelog中的changeSet时,会首先查看DATABASECHANGELOG表,若是已经执行过,则会跳过(除非changeSet的runAlways属性为true),若是没有执行过,则执行并记录changelog日志;

changelog中的一个changeSet对应一个事务,在changeSet执行完后commit,若是出现错误则rollback;

配置

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    password: root
    username: root
    url: jdbc:mysql://localhost:3306/study?useSSL=false&serverTimezone=UTC
  liquibase:
    change-log: classpath:changelog.xml
    user: root
    password: root
    url: jdbc:mysql://localhost:3306/study?useSSL=false&serverTimezone=UTC
    enabled: true
    drop-first: false

依赖

<dependency>
      <groupId>org.liquibase</groupId>
      <artifactId>liquibase-core</artifactId>
</dependency>

changeLog:xml (**就是liquibase里的changelog概念,是可以多层嵌套引用其他changelog的**)
include: 引用changelog的标签
file: 引用changelog文件的质地
changeSet:  一个changeLog可以包含多个changeSet标签,每个changeSet都由id和author以及filepath属性进行唯一标识,当 Liquibase执行数据库changeLog时,它按顺序读取                        changeSet,并针对每个changeSet检查databasechangelog表,以查看是否运行了 id/author/filepath的组合。如果已运行,则将跳过changeSet,除非存在真正的runAlways标签。运行changeSet中所有更改后,Liquibase将 databasechangelog中插入带有 id/author/filepath的新行以及changeSet的MD5Sum。每个changeSet 的事物是单独的,最佳做法是确保每个changeSet都尽可能原子性更改,以避免失败的结果使数据库中剩下的未处理的语句处于unknown 状态。
author:作者
id:changeSet的id(**最好用2019082600-01这种日期的格式,这样更清楚一点,如果是一个目标库可能会被多个项目的liquibase执行到的话,这个id会被写到同一个databasechangelog表        里,可以在日期前面加上项目名或者项目名的缩写来区分,比如reference-2019082600-01)
runAlways:执行每次运行时设置的更改,即使更改之前已运行
context:可以用于灵活控制脚本在哪些环境中执行,我们系统一般定义的是环境(比如team2,uat,prod),多个的话可以用 , or and分割,也支持!prod取反的形式 (**如果定义了context,执行时候就一定要指定contexts,不指定的话会取执行所有的sql,context就失效了)
comment: changeSet的说明。
preConditions:将执行changeSet之前必须通过的前提条件。可用于在做不可恢复的内容之执行数据健全性检查
rollback:描述如何回滚changeSet的 SQL 语句或重构标签
createTable: 创建表的标签
tableName:表名
column: 表字段的标签
name:字段名        
type: 字段类型
remarks: 字段备注  
constraints:字段约束
primaryKey: true代表是主键
nullable: true,false
unique: true,false
createIndex: 创建索引的标签
indexName:索引名
tableName:创建索引的表名
column: 索引字段的标签(多个代表联合索引)
name:字段名 
addColumn: 增加字段的标签
tableName:增加字段的表名
column: 增加的字段
name:字段名     
type: 字段类型
sql: sql标签,内容可以直接是sql语句  
endDelimiter: 要应用于语句末尾的分隔符。默认值为;,可以设置为''。
splitStatement: true,false
stripComments: 设置为 true以在执行之前删除 SQL中的任何注释,否则为 false。如果
 未设置,则默认值为false
comment:注释
sqlFile: 引用sql文件的标签
path:引用sql文件的地址

<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" 
                   xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext" 
                   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
                   xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog-ext 
                                       http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd 
                                       http://www.liquibase.org/xml/ns/dbchangelog 
                                       http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.5.xsd">
    <!-- ################### Table相关 ################### -->
    <!-- 创建表 -->
    <changeSet author="cavan" id="22.1.V1-1">
        <preConditions onFail="MARK_RAN">
            <not>
                <tableExists tableName="school"/>
            </not>
        </preConditions>
        <createTable tableName="school">
            <!-- int类型 -->
            <column name="school_id" type="INT" autoIncrement="true">
                <constraints primaryKey="true" nullable="false"/>
            </column>

            <!-- 字符串类型 -->
            <column name="school_name" type="VARCHAR(100)">
                <constraints nullable="true" unique="false"/>
            </column>

            <!-- 文本类型 -->
            <column name="address" type="TEXT"/>

            <!-- boolean类型 使用boolean或者tinyint(1)-->
            <column name="is_top_ten" type="boolean" defaultValueBoolean="true"/>
            <!-- 方式二
                <column defaultValueNumeric="0" name="is_top_ten" type="tinyint(1)"/>
                -->

            <column defaultValue="anonymity" name="created_by" type="VARCHAR(50)"/>
            <column defaultValueComputed="CURRENT_TIMESTAMP" name="created_date" type="TIMESTAMP">
                <constraints nullable="false"/>
            </column>
            <column defaultValueComputed="CURRENT_TIMESTAMP" name="last_modified_date" type="TIMESTAMP">
                <constraints nullable="false"/>
            </column>
            <column defaultValue="anonymity" name="last_modified_by" type="VARCHAR(50)"/>
        </createTable>	
    </changeSet>

    <changeSet author="cavan" id="22.1.V1-2">
        <preConditions onFail="MARK_RAN">
            <not>
                <tableExists tableName="school_class"/>
            </not>
        </preConditions>
        <createTable tableName="school_class">
            <column name="class_id" type="INT">
                <constraints primaryKey="true" nullable="false"/>
            </column>
            <column name="class_name" type="VARCHAR(100)">
                <constraints nullable="true"/>
            </column>
            <column name="school_id" type="INT">
                <constraints nullable="false"/>
            </column>
        </createTable>	
    </changeSet>

    <!-- 删除表 -->
    <changeSet author="cavan" id="22.1.V1-3">
        <preConditions>
            <tableExists tableName="school_class" />
        </preConditions>
        <dropTable tableName="school_class" />
    </changeSet>

    <!-- 修改表名 -->
    <changeSet author="cavan" id="22.1.V1-4">
        <preConditions>
            <tableExists tableName="school_class" />
        </preConditions>

        <renameTable oldTableName="school_class" 
                     newTableName="class_school"/> 
    </changeSet>


    <!-- ################### 其他相关表操作 ################### -->
    <!-- 增加主键,单一主键 -->
    <changeSet author="cavan" id="22.1.V2-1">
        <addPrimaryKey columnNames="school_id" 
                       constraintName="PRIMARY" 
                       tableName="school"/>
    </changeSet>
    <!-- 增加主键,联合主键 -->
    <changeSet author="cavan" id="22.1.V2-2">
        <addPrimaryKey columnNames="school_id, school_name" 
                       constraintName="PRIMARY" 
                       tableName="school"/>
    </changeSet>

    <!-- 创建索引,删除索引 -->
    <changeSet author="cavan" id="22.1.V2-3">
        <!-- 创建索引 -->
        <createIndex indexName="school_id" tableName="school">
            <column name="school"/>
        </createIndex>
        <!-- 删除索引 -->
        <dropIndex indexName="school_id" tableName="school"/>
    </changeSet>

    <!-- 增加外键约束 -->
    <changeSet author="cavan" id="22.1.V2-4">
        <addForeignKeyConstraint baseColumnNames="school_id" 
                                 baseTableName="school_class" 
                                 constraintName="school_class_ibfk_1" 
                                 deferrable="false" 
                                 initiallyDeferred="false" 
                                 onDelete="RESTRICT" 
                                 onUpdate="RESTRICT" 
                                 referencedColumnNames="school_id" 
                                 referencedTableName="school"/>
    </changeSet>

    <changeSet author="cavan" id="22.1.V2-5">
        <sql>
            ALTER  TABLE school MODIFY COLUMN last_modified_date timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP;
        </sql>
    </changeSet>


    <!-- ################### Column相关 ################### -->
    <!-- 增加字段 -->
    <changeSet author="cavan" id="22.1.V3-1">
        <addColumn tableName="school_class">       
            <column name="school_name" type="VARCHAR(100)">
                <constraints nullable="false"/>
            </column>
        </addColumn>
    </changeSet>

    <!-- 删除字段 -->
    <changeSet author="cavan" id="22.1.V3-2">
        <dropColumn tableName="school">  
            <column name="created_by"/>
            <column name="created_date"/>
            <column name="last_modified_by"/>
            <column name="last_modified_date"/>
        </dropColumn>	
    </changeSet>

    <!-- 修改字段 -->
    <changeSet author="cavan" id="22.1.V3-3">
        <!-- 修改字段名称( 其实可以连带类型一起修改了 ) -->
        <renameColumn tableName="school" oldColumnName="is_top_ten"
                      newColumnName="is_top_ten_new" columnDataType="varchar(20)"/>
        <!-- 修改字段类型 -->
        <modifyDataType tableName="school" columnName="school_name" newDataType="varchar(20)" />
    </changeSet>


    <!-- ################### 数据相关 ################### -->
    <!-- 增删改查数据 -->
    <changeSet author="cavan" id="22.1.V4-1">
        <insert tableName="school">
            <column name="school_id" value="2"/>
            <column name="school_name" value="qinghua"/>
            <column name="created_by" value="anonymity"/>
            <column name="created_date" valueDate="2021-07-20 15:51:53.0"/>
            <column name="last_modified_date" valueDate="2021-07-20 15:51:53.0"/>
            <column name="last_modified_by" value="anonymity"/>
        </insert>
    </changeSet>

    <changeSet author="cavan" id="22.1.V4-2">
        <delete tableName="school">
            <where>school_id='2'</where>
        </delete>
    </changeSet>

    <changeSet author="cavan" id="22.1.V4-3">
        <update tableName="school">
            <column name="school_name" value="beida"/>
            <where>school_id='2'</where>
        </update>
    </changeSet>

    <!-- 基于SQL语句 -->
    <changeSet author="cavan" id="22.1.V5-1">
        <sql>
            insert into school (school_id, school_name, is_top_ten) values (1, 'hafu', 1);
        </sql>
    </changeSet>

    <!-- 基于SQL文件 -->
    <changeSet author="cavan" id="22.1.V5-2">
        <sqlFile path="insert-data.sql"/>
    </changeSet>
</databaseChangeLog>

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
当然,我可以为您提供关于Liquibase的教程。Liquibase是一个用于数据库版本控制的开源工具,它可以帮助您管理数据库模式和数据的变更。 以下是Liquibase教程的一些主要步骤: 1. 安装Liquibase:首先,您需要下载并安装Liquibase。您可以从Liquibase官方网站(https://www.liquibase.org/)下载最新的稳定版本。 2. 配置数据库:在开始使用Liquibase之前,您需要配置您的数据库连接。您可以在Liquibase的配置文件(通常是一个XML文件)中指定数据库的连接URL、用户名和密码等信息。 3. 创建数据库变更脚本:Liquibase使用变更脚本来跟踪数据库的变化。您可以通过编写包含DDL(数据定义语言)和DML(数据操作语言)语句的XML、YAML或SQL文件来定义这些变更。每个变更脚本都有一个唯一的标识符,以便Liquibase可以跟踪和应用它们的顺序。 4. 运行Liquibase命令:一旦您创建了数据库变更脚本,您可以使用Liquibase命令行工具来执行这些变更。例如,您可以使用"liquibase update"命令来应用尚未应用的变更。 5. 版本控制:Liquibase允许您对数据库模式和数据进行版本控制。您可以使用"Liquibase update"命令来将数据库更新到特定版本。此外,Liquibase还提供了回滚和验证等功能,以便您可以管理和维护数据库的变化历史记录。 这只是Liquibase教程的一个简单概述,您可以在Liquibase官方文档中找到更详细的信息和示例。祝您使用Liquibase愉快!如果您有任何进一步的问题,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值