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



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

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

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

    准备工作

    引入依赖:

                <dependency>
                    <groupId>org.liquibasegroupId>
                    <artifactId>liquibase-coreartifactId>
                    <version>4.3.5version>
                dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    添加配置:

    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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    初始化change_log

    创建文件:

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

    00000000000000_initial_schema.xml:

    
    <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>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    changelog-master.xml:

    
    
    
        
        
        
        
        
        
        
        
        
    
        
       
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    添加插件:

    在pom文件中添加插件:

    <build>
            <plugins>
                <plugin>
                    <groupId>org.liquibasegroupId>
                    <artifactId>liquibase-maven-pluginartifactId>
                    <version>3.5.3version>
                    <configuration>
                        
                        <changeLogFile>${basedir}/src/main/resources/config/liquibase/changelog-master.xmlchangeLogFile>
                        <diffChangeLogFile>${basedir}/src/main/resources/config/liquibase/changelog/${maven.build.timestamp}_changelog.xmldiffChangeLogFile>
                        <outputChangeLogFile>${basedir}/src/main/resources/config/liquibase/changelog/00000000000000_initial_schema.xmloutputChangeLogFile>
    
                        <driver>com.mysql.cj.jdbc.Driverdriver>
                        <url>jdbc:mysql://ip:port/databaseurl>
                        <username>usernameusername>
                        <password>passwordpassword>
    
                        
                        <promptOnNonLocalDatabase>falsepromptOnNonLocalDatabase>
                        
                        <outputFileEncoding>UTF-8outputFileEncoding>
                        
                        <verbose>trueverbose>
                        
                        <propertyFileWillOverride>truepropertyFileWillOverride>
                        <rollbackTag>${project.version}rollbackTag>
                        <tag>${project.version}tag>
                    configuration>
                plugin>
            plugins>
        build>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

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

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

    编写change_log

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

    change_log_20221024.xml:

    
    <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>
    
        
        <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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

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

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

    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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    创建表:

        <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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    删除字段:

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

    添加字段:

        <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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

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

        <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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    and so on…

    注意事项

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

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

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

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

  • 相关阅读:
    Spring Boot 集成 zxing 生成条形码与二维码
    Static 静态成员
    Docker发布镜像时报错denied: requested access to the resource is denied解决办法
    Goby 漏洞发布|Honeywell PM43 loadfile.lp 文件命令执行漏洞(CVE-2023-3710)
    【react】精选5题
    冠达管理:打新股的风险有多大?
    java-php-net-python-文献资料管理系统计算机毕业设计程序
    @Transaction注解的应用
    基于Node.js 和 FFmpeg构建自动化脚本用来转码视频
    微信小程序使用echarts/数据刷新重新渲染/图层遮挡问题
  • 原文地址:https://blog.csdn.net/sinat_14840559/article/details/127685989