飞道的博客

【Java】记录一次使用 Springboot + Liquibase 做数据库的变更同步、回滚

624人阅读  评论(0)


本次项目中Liquibase主要用来做以下工作:

  1. 基于开发环境数据库,同步数据表结构至测试环境和线上环境
  2. 数据库变更同步、回滚

官方地址:https://docs.liquibase.com/home.html

准备工作

引入依赖:

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

添加配置:

spring:
  datasource: 
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://ip:port/database?useUnicode=true&characterEncoding=utf8&useSSL=false
    username: username
    password: password
  liquibase:
    change-log: classpath:/config/liquibase/changelog-master.xml # changelog入口文件
    enabled: true

初始化change_log

创建文件:

(省略这一步,不知道会不会报文件或目录不存在,我是直接都创建了)

00000000000000_initial_schema.xml:

<?xml version="1.0" encoding="utf-8"?>
<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 http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.3.xsd
                        http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd">
       
</databaseChangeLog>

changelog-master.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-4.3.xsd">

    <property name="now" value="now()" dbms="h2"/>
    <property name="now" value="now()" dbms="mysql, mariadb"/>
    <property name="floatType" value="float4" dbms="postgresql, h2"/>
    <property name="floatType" value="float" dbms="mysql, oracle, mssql, mariadb"/>
    <property name="clobType" value="clob" dbms="h2"/>
    <property name="clobType" value="clob" dbms="mysql, oracle, mssql, mariadb, postgresql"/>
    <property name="uuidType" value="varchar(36)" dbms="h2, mysql, mariadb"/>
    <property name="datetimeType" value="datetime(0)" dbms="mysql, mariadb"/>
    <property name="datetimeType" value="datetime" dbms="oracle, mssql, postgresql, h2"/>

    <include file="config/liquibase/changelog/00000000000000_initial_schema.xml" relativeToChangelogFile="false"/>
   
</databaseChangeLog>

 

添加插件:

在pom文件中添加插件:

<build>
        <plugins>
            <plugin>
                <groupId>org.liquibase</groupId>
                <artifactId>liquibase-maven-plugin</artifactId>
                <version>3.5.3</version>
                <configuration>
                    <!--指定执行主文件 -->
                    <changeLogFile>${basedir}/src/main/resources/config/liquibase/changelog-master.xml</changeLogFile>
                    <diffChangeLogFile>${basedir}/src/main/resources/config/liquibase/changelog/${maven.build.timestamp}_changelog.xml</diffChangeLogFile>
                    <outputChangeLogFile>${basedir}/src/main/resources/config/liquibase/changelog/00000000000000_initial_schema.xml</outputChangeLogFile>

                    <driver>com.mysql.cj.jdbc.Driver</driver>
                    <url>jdbc:mysql://ip:port/database</url>
                    <username>username</username>
                    <password>password</password>

                    <!-- 是否需要弹出确认框 -->
                    <promptOnNonLocalDatabase>false</promptOnNonLocalDatabase>
                    <!--输出文件的编码 -->
                    <outputFileEncoding>UTF-8</outputFileEncoding>
                    <!--执行的时候是否显示详细的参数信息 -->
                    <verbose>true</verbose>
                    <!--是否每次都重新加载properties -->
                    <propertyFileWillOverride>true</propertyFileWillOverride>
                    <rollbackTag>${project.version}</rollbackTag>
                    <tag>${project.version}</tag>
                </configuration>
            </plugin>
        </plugins>
    </build>

 

该插件用于逆向生成初始化Liquibase Changelog文件,添加完插件后,在右侧Maven栏可看到该插件

注意:此步骤是基于现有的数据库内的表结构,生成初始化change_log文件,比如使用测试环境的数据库结构,生成change_log文件后,线上启动项目会自动创建对应的数据表。

编写change_log

当生成了初始化的change_log后,再有数据库的变更,最好不要在初始化的文件中直接修改,Liquibase会为初始化文件中的每张表的内容生成一个MD5值,每次项目启动时,会去校验初始化文件中的内容是否有变更,如果有变更,会启动报错,所以如果有新的结构变更,最好是创建新的change_log文件,然后在入口文件changelog-master.xml中进行引入,比如:

change_log_20221024.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-4.3.xsd">

    <changeSet id="20221024" author="zhurunhua">
        <tagDatabase tag="20221024"/>
    </changeSet>

    <!--user表添加name字段-->
    <changeSet id="20221024_1" author="zhurunhua">
        <addColumn tableName="user">
            <column name="name" type="varchar(64)" remarks="名称" afterColumn="id">
                <constraints nullable="true"/>
            </column>
        </addColumn>
    </changeSet>
</databaseChangeLog>

 

在changelog-master.xml文件中添加:

    <include file="config/liquibase/changelog/change_log_20221024.xml" relativeToChangelogFile="false"/>

Liquibase的change_log支持很多种语法,几乎涵盖了所有的数据库变更操作,比如添加表、添加索引、删除表、删除字段、添加字段等等,也支持对每次变更指定回滚操作,具体的使用细节,可以在使用中摸索。

示例:

删除表:(如果后续可能会回滚,则加上回滚逻辑)

    <changeSet id="20221024_18" author="zhurunhua">
        <dropTable tableName="student"/>
        <rollback>
            <createTable tableName="student">
                <column name="name" remarks="姓名" type="varchar(32)">
                    <constraints nullable="false"/>
                </column>
                <column name="update_time" remarks="更新日期" type="datetime(0)">
                    <constraints nullable="false"/>
                </column>
                <column name="creation_time" remarks="创建日期" type="datetime(0)">
                    <constraints nullable="false"/>
                </column>
            </createTable>
        </rollback>
    </changeSet>

 

创建表:

    <changeSet id="20221024_20" author="zhurunhua">
        <createTable tableName="teacher">
            <column autoIncrement="true" name="id" remarks="id" type="BIGINT">
                <constraints primaryKey="true"/>
            </column>
            <column name="name" remarks="更新日期" type="varchar(32)">
                <constraints nullable="false"/>
            </column>
            <column name="creation_time" remarks="创建日期" type="datetime(0)">
                <constraints nullable="false"/>
            </column>
        </createTable>
    </changeSet>

删除字段:

    <changeSet id="20221024_21" author="zhurunhua">
        <dropColumn tableName="teacher" columnName="name"/>
    </changeSet>

添加字段:

    <changeSet id="20221024_17" author="zhurunhua">
        <addColumn tableName="rdb_database">
            <column name="sex" type="TINYINT(3)" remarks="性别;0:男 1:女" afterColumn="name">
                <constraints nullable="true"/>
            </column>
        </addColumn>
    </changeSet>

修改字段类型、修改字段是否非必填:

    <changeSet id="20221101_5" author="zhurunhua">
        <modifyDataType columnName="sex" newDataType="TINYINT" tableName="student"/>
        <!--修改为非必填-->
        <dropNotNullConstraint columnDataType="TINYINT" tableName="student" columnName="state"/>
        <!--修改为必填-->
        <addNotNullConstraint tableName="student" columnDataType="varchar(32)" columnName="address"/>
    </changeSet>

and so on…

注意事项

  • 第一次启动项目执行完数据库信息同步后,会生成两张表,这两张表主要记录每次执行的数据库变更,不要删除。

  • 已执行过的change_log文件不要轻易修改,如果数据库变更太多,实在要修改,可以将里面的内容删除,重新生成。

  • 如果由于Liquibase导致项目启动卡住,多半是因为锁,将表:DATABASECHANGELOGLOCK 中的锁记录删除,再重启项目。

  • 初始化生成的change_log文件最好检查一下,看看数据字段类型、长度是否符合预期。


转载:https://blog.csdn.net/sinat_14840559/article/details/127685989
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场