Liquibase+SpringBoot的簡單使用筆記!update+rollback

  • 2020 年 11 月 5 日
  • 筆記

該筆記記錄了springboot整合liquibase之後,如何根據liquibase ChangeLogFile對資料庫進行修改以及回滾操作

參考:
baeldung.com
JHipster

1. 利用changeLog文件對資料庫進行修改

  1. 引入liquibase依賴
  2. 在resource目錄下新建db.changelog-master.xml作為變更集文件
  3. 修改application加入liquibase的配置,主要配置變更集文件位置
  4. 運行項目,即可根據變更集文件的內容對資料庫進行修改

master.xml簡單格式:

<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="//www.liquibase.org/xml/ns/dbchangelog" xmlns:ext="//www.liquibase.org/xml/ns/dbchangelog-ext" xmlns:pro="//www.liquibase.org/xml/ns/pro" xmlns:xsi="//www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="//www.liquibase.org/xml/ns/dbchangelog-ext //www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd //www.liquibase.org/xml/ns/pro //www.liquibase.org/xml/ns/pro/liquibase-pro-3.10.xsd //www.liquibase.org/xml/ns/dbchangelog //www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.10.xsd">
    <changeSet author="chunmiaoz (generated)" id="1604474279717-1">
        <createTable tableName="user">
            <column name="id" type="BIGINT">
                <constraints nullable="false" primaryKey="true"/>
            </column>
            <column name="phone" type="VARCHAR(11)"/>
            <column name="username" type="VARCHAR(255)">
                <constraints nullable="false"/>
            </column>
        </createTable>
    </changeSet>
</databaseChangeLog>

2. 從現有資料庫表生成changeLog文件

  1. 在資料庫中建表
  2. 新建一個liquibase.properties並配置資料庫地址、用戶名密碼、驅動
  3. 在有liquibase.properties的目錄下打開cmd,輸入命令
liquibase --changeLogFile=dbchangelog.xml generateChangeLog

會自動生成一個dbchangelog.xml的目標文件
Liquibase可根據目標文件後綴名生成對應類型的變更集文件,如.yaml會生成yaml格式的

liquibase.properties:

# Enter the path for your changelog file.
changeLogFile=dbchangelog.xml

#### Enter the Target database 'url' information  ####
url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8&useSSL=false&useLegacyDatetimeCode=false&serverTimezone=UTC&createDatabaseIfNotExist=true

# Enter the username for your Target database.
username: root

# Enter the password for your Target database.
password: 123456

3. 從使用JPA導出的jar包生成changeLog文件

  1. 新建一個項目,引入jpa依賴
  2. 修改application,配置jpa的ddl-auto屬性為create
  3. 新建實體類
  4. 將項目打包成jar文件
  5. 在jar文件目錄下,新建liquibase.properties並配置相應的屬性
  6. 在該目錄打開cmd,輸入命令
Liquibase --logLevel=INFO --defaultsFile=liquibase.properties generateChangeLog  

即可自動生成dbchangelog.xml文件

Liquibase.properties:

# jar包地址
classpath=liquibase-demo-0.0.1-SNAPSHOT.jar

# Enter the path for your changelog file.
changeLogFile=dbchangelog.xml

#### Enter the Target database 'url' information  ####
url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8&useSSL=false&useLegacyDatetimeCode=false&serverTimezone=UTC&createDatabaseIfNotExist=true

# Enter the username for your Target database.
username: root

# Enter the password for your Target database.
password: 123456

4. 回滾Liquibase生成的資料庫

利用liquibase的命令

liquibase update

生成的資料庫表單,可以利用命令使資料庫回滾

liquibase rollbackCount 1 //回滾一條記錄
liquibase rollbackToDate YYYY-MM-DD HH:MM:SS //回滾到指定日期

5. Springboot集成的liquibase回滾操作

通過借鑒jhipster的liquibase配置結構完成此功能
前提:liquibase回滾時,要求databasechangelog和更改集文件一致。

  1. 在項目中,resource目錄下配置master.xml主變更集文件,目的是將子更改集include進來
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="//www.liquibase.org/xml/ns/dbchangelog" xmlns:ext="//www.liquibase.org/xml/ns/dbchangelog-ext" xmlns:pro="//www.liquibase.org/xml/ns/pro" xmlns:xsi="//www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="//www.liquibase.org/xml/ns/dbchangelog-ext //www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd //www.liquibase.org/xml/ns/pro //www.liquibase.org/xml/ns/pro/liquibase-pro-3.10.xsd //www.liquibase.org/xml/ns/dbchangelog //www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.10.xsd">
    <include file="db/changelog/202011051610-added-person.xml" relativeToChangelogFile="false"></include>
</databaseChangeLog>
  1. 新建202011051610-added-person.xml子變更集文件,位置為src\main\resources\db\changelog\db.changelog-master.xml
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="//www.liquibase.org/xml/ns/dbchangelog" xmlns:ext="//www.liquibase.org/xml/ns/dbchangelog-ext" xmlns:pro="//www.liquibase.org/xml/ns/pro" xmlns:xsi="//www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="//www.liquibase.org/xml/ns/dbchangelog-ext //www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd //www.liquibase.org/xml/ns/pro //www.liquibase.org/xml/ns/pro/liquibase-pro-3.10.xsd //www.liquibase.org/xml/ns/dbchangelog //www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.10.xsd">
    <changeSet author="chunmiaoz (generated)" id="1604474279717-1">
        <createTable tableName="user">
            <column name="id" type="BIGINT">
                <constraints nullable="false" primaryKey="true"/>
            </column>
            <column name="phone" type="VARCHAR(11)"/>
            <column name="username" type="VARCHAR(255)">
                <constraints nullable="false"/>
            </column>
        </createTable>
    </changeSet>

    <changeSet id="202011041617-added-person" author="Chunmiao">
        <createTable tableName="person">
            <column name="id" type="INT">
                <constraints primaryKey="true" nullable="false" unique="true" ></constraints>
            </column>
            <column name="name" type="VARCHAR(255)">
                <constraints nullable="false"></constraints>
            </column>
            <column name="address" type="VARCHAR(255)"></column>
            <column name="city" type="VARCHAR(255)"></column>
        </createTable>
    </changeSet>

    <changeSet id="202011041621-added-company" author="Chunmiao">
        <createTable tableName="company">
            <column name="id" type="INT">
                <constraints primaryKey="true" nullable="false" unique="true"></constraints>
            </column>
            <column name="name" type="VARCHAR(255)">
                <constraints nullable="false"></constraints>
            </column>
            <column name="address" type="VARCHAR(255)"></column>
            <column name="city" type="VARCHAR(255)"></column>
        </createTable>
    </changeSet>

    <changeSet id="202011041621-alert-person" author="Chunmiao">
        <addColumn tableName="person">
            <column name="country" type="VARCHAR(2)">
            </column>
        </addColumn>

        <rollback>
            <dropColumn tableName="person" columnName="country"></dropColumn>
        </rollback>
    </changeSet>
</databaseChangeLog>
  1. 修改pom.xml,為maven增加liquibase插件
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
            <plugin>
                <groupId>org.liquibase</groupId>
                <artifactId>liquibase-maven-plugin</artifactId>
                <configuration>
                    <changeLogFile>${basedir}/src/main/resources/db/changelog/db.changelog-master.xml</changeLogFile>
                    <url>jdbc:mysql://localhost:3306/test?serverTimezone=GMT%2B8</url>
                    <username>root</username>
                    <password>123456</password>
                </configuration>
            </plugin>
        </plugins>
  1. 運行項目,可以發現liquibase會自動創建資料庫表
  2. 執行回滾操作,在命令行中利用maven命令
    mvn liquibase:rollback -Dliquibase.rollbackCount=1
  3. 利用maven執行變更集任務可以使用命令
    mvn liquibase:update

已知問題:
在springBoot中,由於liquibase update是由springBoot完成的,手動在命令行中對該changeLog執行回滾操作,雖然會提示成功,但是資料庫中的數據實際沒有發生回滾。

原因:
springBoot中changelogFile位置為classpath:db/changelog/db.changelog-master.xml
而在命令行中,無法將文件位置表示為classpath:的形式,文件名字不同會被liquibase認為是不同的版本管理

解決方法:
將changeSet定義在子變更集中,在主變更集中引入子變更集,這樣不管在什麼環境里,changeSet的路徑都被表示為在主變更集中配置的一樣,從而避免了路徑不同的衝突