liquibase常用操作
1、概述
Liquibase是一个用于跟踪、管理和应用数据库变化的开源的数据库重构工具。它将所有数据库的变化(包括结构和数据)都保存在XML文件中,便于版本控制。
本文旨在将平时工作中常用的一些操作进行了整理,方便给大家提供参考。
2、理解databasechangelog和databasechangeloglock表
LiquiBase在执行changelog时,会在数据库中插入两张表:DATABASECHANGELOG
和DATABASECHANGELOGLOCK
,分别记录changelog的执行日志和锁日志。
LiquiBase在执行changelog中的changeSet时,会首先查看DATABASECHANGELOG
表,若是已经执行过,则会跳过(除非changeSet的runAlways
属性为true),若是没有执行过,则执行并记录changelog日志;
changelog中的一个changeSet对应一个事务,在changeSet执行完后commit,若是出现错误则rollback;
<changeSet>
标签的主要属性有:dom
- runAlways:即便已经执行过,仍然每次都执行;注意: 因为
DATABASECHANGELOG
表中还记录了changeSet的MD5校验值MD5SUM,若是changeSet的id
和name
没变,而内容变了,则因为MD5值变了,即便runAlways的值为True,执行也是失败的,会报错。这种状况应该使用runOnChange
属性。 - runOnChange:第一次的时候执行以及当changeSet的内容发生变化时执行。不受MD5校验值的约束。
- runInTransaction:是否做为一个事务执行,默认为true。设置为false时须要当心:若是执行过程当中出错了则不会rollback,数据库极可能处于不一致的状态;
关于数据库liquibase表DATABASECHANGELOG 字段 MD5SUM:
- 当changeSet为建立表,删除表,新增字段时 改变MD5SUM 的值
- 当changeSet为loadDate或loadUpdateData 改变csv的值,改变MD5SUM 的值
-
当数据库和MD5sum不一致时直接改数据库值会产生报错
3、changelog文件--支持XML
<?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>
参考链接:
博客:
https://blog.csdn.net/lqzkcx3/article/details/108384404
http://www.javashuo.com/article/p-cyylquuc-eb.html
官方网站:
https://docs.liquibase.com/change-types/home.html