相关文章推荐
飞翔的感冒药  ·  Oracle Application ...·  1 年前    · 

官方网站:

www.liquibase.org

在实际开发中,数据库中的表设计往往不是一成不变的,可能在某个版本中我们需要加入几个字段;或者加入一张表;修改某个字段的约束;添加一些初始数据;等等…… 而在个人开发中,这种修改造成的影响尚可以忍受,毕竟自己知道数据库做了哪些更改,或者自己记录了文档方便自己回溯。 但是,在团队开发中,数据库的版本修改造成的影响就比较大了,例如:

  • 团队中某个成员没有同步更新数据库,影响开发进度
  • 由于没有同步更新数据库,某个成员使用了错误的数据
  • 除了数据库版本不一致对开发带来的影响之外,还有一些原因让我们需要 Liquibase:

  • 手工管理数据库版本,繁琐
  • 没有一致的方法管理数据库版本变更
  • 日志不好维护
  • Liquibase 能够让开发者通过日志的方式记录数据库版本的变更,执行日志中的修改,将数据库更新,或者回滚到某一个版本。Liquibase 有如下特点:

  • 支持几乎所有主流的数据库:MySQL,Oracle,SQLServer 等
  • 支持多开发者的协作维护
  • 日志文件支持多种格式,xml,yaml,json,sql 等
  • 支持多种运行方式,命令行、Maven 插件、Gradle 插件等
  • 本文将通过 maven 插件的方式演示如何使用 Liquibase

    🚀初试 Liquibase

    初始化项目

    使用 IDEA 新建一个 SpringBoot 项目,不使用任何依赖,下面的 pom.xml 文件列出需要用到的依赖和插件

    <dependencies>
        <!-- 一个 SpringBoot 项目 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
            <version>2.3.7.RELEASE</version>
        </dependency>
        <!-- MySQL 驱动 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
            <version>5.1.49</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <!-- Liquibase 插件 -->
            <plugin>
                <groupId>org.liquibase</groupId>
                <artifactId>liquibase-maven-plugin</artifactId>
                <version>4.17.2</version>
                <configuration>
                    <promptOnNonLocalDatabase>false</promptOnNonLocalDatabase>
                    <!-- liquibase 的配置文件位置 -->
                    <propertyFile>db/liquibase-mysql.properties</propertyFile>
                    <!-- 设置每次回滚的变更集数 -->
                    <rollbackCount>1</rollbackCount>
                </configuration>
            </plugin>
        </plugins>
    </build>
    

    编写 application.yml

    spring:
      application:
        name: Liuqibase-demo
      datasource:
        driver-class-name: com.mysql.jdbc.Driver
        username: root
        password: 123456
        url: jdbc:mysql://localhost:3306/test?serverTimezone=UTC
    

    编写 Liquibase 的配置文件

    在资源目录下新建目录db,在该目录下编写 Liquibase 的配置文件 liquibase-mysql.properties,主要配置使用的数据库的基本信息

    driver=com.mysql.jdbc.Driver
    url=jdbc:mysql://localhost:3306/test?serverTimezone=UTC
    username=root
    password=123456
    # 变更日志文件的入口
    changeLogFile=db/changelog-master.xml
    

    编写变更日志

    在资源目录的db目录下存放数据库相关文件,目录结构如下:

    # 资源目录
    	- 1.0.0												# 数据库 1.0.0 版本
      	- changelog.xml							# 变更日志
    	- changelog-master.xml				# 数据库变更日志主入口文件
    	- liquibase-mysql.properties	# liquibase 配置文件
    

    Liquibase 的 xml 文件的基础模板如下:

    <?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.8.xsd">
    </databaseChangeLog>
    

    db目录下创建数据库变更日志主入口文件:changelog-master.xml,Liquibase 会根据包含关系层层往下,执行变更集。

    <?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.8.xsd">
      <!-- 包含的变更日志 -->
      <include file="1.0.0/changelog.xml" relativeToChangelogFile="true"/>
      <!-- 当变更日志数量庞大时,也可以使用 includeAll 包含一个目录,这将引入目录下的所有变更日志 -->
    </databaseChangeLog>
    

    db\1.0.0 目录下创建变更日志:changelog.xml

    <?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.8.xsd">
      <!-- 变更集,必须指定 id 和 author -->
      <changeSet id="1.0.0-20221107" author="abc">
        <!-- 主要操作,创建一张表 -->
        <createTable tableName="test_liquibase">
          <column name="id" type="varchar(50)" remarks="主键">
            <constraints primaryKey="true" />
          </column>
          <column name="name" type="varchar(50)" remarks="名字"/>
        </createTable>
        <!-- 这个变更集的回滚操作 -->
        <rollback>
          <dropTable tableName="test_liquibase"/>
          <!-- 也可以直接编写sql,例如下面的示例 -->
          <!-- <sql>drop table test_liquibase</sql>-->
        </rollback>
      </changeSet>
    </databaseChangeLog>
    

    执行版本变更

    ❗❗❗ 注意,每次修改了变更日志,都需要执行 maven 的生命周期插件 package 重新打包,将变更日志文件更新到 target目录中。

    使用 maven 插件:liquibase:update 将数据库变更更新到数据库中,执行成功后应该能看到如下语句:

    [INFO] BUILD SUCCESS
    

    💡可以使用 liquibase:help 查看插件的使用说明

    初次执行成功后,会在指定的数据库中添加两张表databasechangelogdatabasechangeloglock,这是Liquibase 维护变更日志的。 查看数据库,可以看到我们的添加表的操作成功执行了:

    继续修改数据库版本

    database 目录下创建 2.0.0 目录,创建变更日志:changelog.xml

    <?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.8.xsd">
      <changeSet id="2.0.0-20221107" author="abc">
        <!-- 新增加一个字段 -->
        <addColumn tableName="test_liquibase">
          <column name="age" type="int(1)" remarks="年龄"/>
        </addColumn>
        <!-- 回滚操作 -->
        <rollback>
          <dropColumn tableName="test_liquibase" columnName="age"/>
        </rollback>
      </changeSet>
      <changeSet id="insert" author="abc">
        <!-- 该变更集的主要操作为执行一段 sql,添加数据 -->
        <!-- sqlFile 标签配置要执行的 sql 脚本 -->
        <sqlFile path="data.sql" relativeToChangelogFile="true"/>
        <rollback>
          <!-- 回滚脚本 -->
          <sqlFile path="rollback.sql" relativeToChangelogFile="true"/>
        </rollback>
      </changeSet>
    </databaseChangeLog>
    

    2.0.0目录下分别创建 data.sqlrollback.sql 文件

    -- liquibase formatted sql
    -- changeset abc:data-20221107
    insert into test_liquibase values ('11111', 'name', 18);
    
    -- liquibase formatted sql
    -- changeset abc:rollback-20221107
    delete from test_liquibase where id='11111';
    

    ❗❗❗ sql 脚本中,文件开头需要编写如下文本,标识作者,id

    -- liquibase formatted sql
    -- changeset author:id
    

    执行变更,执行 maven 插件 liquibase:update,查看结果:

    mysql> select * from test_liquibase;
    +-------+------+------+
    | id    | name | age  |
    +-------+------+------+
    | 11111 | name |   18 |
    +-------+------+------+
    1 row in set (0.00 sec)
    

    进行回滚操作

    执行一次 maven 插件操作:liquibase:rollback,根据上面的配置文件的设置,Liquibase 会回滚一个变更集,即将刚才插入的数据删除。 查看结果:

    mysql> select * from test_liquibase;
    Empty set (0.00 sec)
    

    🚀一些标签的说明

  • <include>,包含另一个变更集文件,一般主入口文件使用该标签,去包含变更版本中的变更日志文件
  • <includeAll>,包含整个目录中变更集文件
  • <changeSet>标签对应一个变更集,即一个变更操作,通常一个变更日志文件中会有该标签或者<include>。一些常见属性:
  • id:唯一,标识该变更集
  • author:该变更集的作者
  • dbms:执行的数据库
  • changeSet 的子标签:
  • <sql>,编写一段 sql 脚本
  • <sqlFile>,引用其他 sql 脚本文件
  • <createTable>,创建一张表
  • <addColumn>,添加一个字段
  • <rollback>,回滚操作
  • 🚀注意点

    在实际使用过程中,建议一个变更版本使用一个变更日志主文件,包含其他变更日志,一个变更日志对应一个日志文件。 对于数据的插入操作,建议使用 sql 脚本的方式插入,这样文件结构看起来更清晰。

    - database
    	- 1.0.0
      	- data.sql
      	- XxxChangeSet1.xml
    		- XxxChangeSet2.xml
      	- changelog.xml
    	- changelog-master.xml
    

    liquibase 的 maven 插件的使用说明,可以使用其提供的插件:liquibase:help进行查看

    Liquibase 可以帮助我们管理数据库版本,使得数据库版本能够与应用程序版本一致,便于开发维护。

    本文介绍了 Liquibase 的简单用法,更多用法还请参考官网自行学习。

  • 在 React Router 中使用 JWT
  • 开发者故事 #8 微软 New Bing AI 申请与使用保姆级教程
  • 手把手教你注册和使用ChatGPT
  • ChatGPT保姆级教程,一分钟学会使用ChatGPT!
  • 私信