SpringBoot 集成 Liquibase
1.引入maven依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.1.5</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>cn.com.servision.liquibase</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo</name>
<description>demo</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- liquibase -->
<dependency>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-core</artifactId>
</dependency>
<!-- 添加数据库驱动依赖,例如MySQL -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!-- 添加MyBatis依赖 -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.2</version>
</dependency>
<!-- MySQL 8 connector -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.28</version>
</dependency>
</dependencies>
</project>
2.修改配置文件
server:
port: 9001
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/liquibase_demo
username: root
liquibase:
change-log: classpath:/liquibase/db.changelog-master.xml
enabled: true
contexts: dev
change-log 属性指定变更日志文件位置。 该文件配置着需要同步的数据库结构。 如果需要执行多个变更日志文件,查看下面执行单个和多个变更日志文件的示例。
3.创建 change-log 文件
在配置文件 spring.liquibase.change-log 指定 db.changelog-master.xml 文件
下面是 db.changelog-master.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:pro="http://www.liquibase.org/xml/ns/pro" 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/pro http://www.liquibase.org/xml/ns/pro/liquibase-pro-latest.xsd http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-latest.xsd">
<changeSet author="kafeim (generated)" id="1699778673366-1" context="dev">
<createTable remarks="用户" tableName="t_user">
<column autoIncrement="true" name="id" type="BIGINT">
<constraints nullable="false" primaryKey="true"/>
</column>
<column name="username" remarks="名称" type="VARCHAR(255)"/>
<column name="password" remarks="密码" type="VARCHAR(255)"/>
</createTable>
</changeSet>
</databaseChangeLog>
需要注意的是 changeSet 标签中的 context="dev" 对应着 spring.liquibase.contexts 的值 spring.liquibase.contexts的值可以是多个的。
应用启动的时候回去执行 对应 contexts 值的 changeSet标签的内容。
1. 如果想执行多个变更日志
执行多个变更文件,使用includeAll标签 ,指定需要执行变更文件的文件夹,项目启动时会将配置的文件夹下的变更日志全部执行一遍。
需要注意的是,执行的顺序是按照字母的排序顺序来的,有执行先后顺序的要求,需要把文件名规范一下。如 001.xml 002.xml
<!-- src/main/resources/db/changelog/db.changelog-master.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-3.8.xsd">
<!-- 引用其他变更日志文件 -->
<includeAll path="classpath:/liquibase/changelog" context="dev" />
</databaseChangeLog>
2. 如果只是想执行指定的几个文件可以使用下面的配置
<!-- src/main/resources/db/changelog/db.changelog-master.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-3.8.xsd">
<!-- 引用其他变更日志文件 -->
<include file="classpath:/db/changelog/changes/001-initial-schema1.xml" context="dev" />
!-- 引用其他变更日志文件 -->
<include file="classpath:/db/changelog/changes/001-initial-schema2.xml" context="uat"/>
</databaseChangeLog>
xml 中 include 或者是 changeSet 标签的 context 不是必填的,但是如果配置文件中spring.liquibase.contexts 指定了要执行的上下文,那么你想要执行的变更文件的标签也要带上相应的 context。
4.启动应用执行变更文件
当你看到控制台输出成功,并且数据库中有 DATABASECHANGELOG 表 ,还有执行的变更日志的记录,就说明成功了。
5.liquibase 变更日志执行的逻辑
- 检查
DATABASECHANGELOG表: Liquibase 首先检查DATABASECHANGELOG表是否存在于当前数据库中。如果表不存在,Liquibase 会创建它。 - 查询已执行的变更集: Liquibase 会查询
DATABASECHANGELOG表以确定哪些变更集已被执行。每个已执行的变更集都记录了id、author和filename。 - 变更集唯一性检查: 对于要执行的每个变更集,Liquibase 会检查
DATABASECHANGELOG表中是否已存在相同的id、author和filename的组合。如果这样的记录存在,它表明该变更集已经被执行过,因此 Liquibase 将跳过它。 - 上下文和标签过滤: 如果为变更集指定了
context或label,Liquibase 还会检查这些属性是否与运行时指定的上下文或标签匹配。只有当它们匹配或未定义时,变更集才会被执行。 - 执行变更集: 对于那些未在
DATABASECHANGELOG表中记录的变更集,Liquibase 会执行它们,并在执行后将它们添加到DATABASECHANGELOG表中,这样在未来的运行中,Liquibase 就知道这些变更集已经被执行过了。 - 记录执行细节: 当一个变更集被执行时,Liquibase 会在
DATABASECHANGELOG表中插入一条新记录,包含变更集的id、author、filename,以及执行时间、订单号(orderexecuted)、执行类型(EXECTYPE)等信息。这样即使在多次执行过程中,变更集也不会被执行第二次。 在DATABASECHANGELOG表中,id、author、filename以及contexts这些列一起用来确定变更集是否已经被执行。但是,只有id、author和filename用来标识变更集的唯一性。context则用来决定在给定的运行上下文中是否应该执行变更集。 - MD5SUM:Liquibase 已经执行并记录了校验和的变更集(changeSet)上做了修改,那么下次尝试运行项目启动时的 Liquibase 迁移时,它会报错。Liquibase 会在启动时尝试校验每个变更集的校验和,如果发现校验和与
DATABASECHANGELOG表中记录的不一致,它会抛出错误,并且不会执行任何进一步的数据库迁移。这里的校验和 指的是数据库中 MD5SUM 字段。