Liquibase作为一款开源的数据库架构变更管理工具,可以帮助开发者方便跟踪、管理数据库变化的修订。其支持MySQL、PostgreSQL、Oracle等众多数据库
集成Spring
Spring boot内置了对Liquibase的支持,只需要在项目中引入Liquibase依赖并进行配置即可
1 2 3 4 5 6
| <dependency> <groupId>org.liquibase</groupId> <artifactId>liquibase-core</artifactId> <version>3.6.3</version> </dependency>
|
对于配置而言,Liquibase默认会使用Spring配置项的数据库连接。如果期望不使用该默认配置,也可以显式单独配置
1 2 3 4 5 6 7 8 9 10
| spring.datasource.driver-class-name=com.mysql.jdbc.Driver spring.datasource.url=jdbc:mysql://localhost:3306/db1?useSSL=false spring.datasource.username=root spring.datasource.password=123456
spring.liquibase.enabled=true
spring.liquibase.change-log=classpath:/db/changelog/master.xml
|
在上面的配置项spring.liquibase.change-log中我们指定了Liquibase 变更记录的位置。事实上,通常这只是一个master配置文件,如下所示。其中通过include标签来包含、汇聚所有的changlog文件
1 2 3 4 5 6 7 8 9 10 11 12
| <?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.9.xsd">
<include file="changelog-1.0.xml" relativeToChangelogFile="true"/>
</databaseChangeLog>
|
目录结构如下所示
详解ChangeLog
一个典型地changlog文件如下所示,其记录了我们对数据库的变更、修订内容。这里我们使用XML进行介绍,其实Liquibase支持SQL、XML、JSON、YAML等多种形式
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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
| <?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.9.xsd">
<changeSet id="create_density_range" author="Aaron" runOnChange="true"> <preConditions onError="MARK_RAN" onFail="MARK_RAN"> <not> <tableExists tableName="density_range"/> </not> </preConditions>
<createTable remarks="密度区间" tableName="density_range"> <column name="id" type="INTEGER" remarks="主键id" autoIncrement="true" startWith="1" incrementBy="1"> <constraints primaryKey="true" nullable="false"/> </column> <column name="low_start" remarks="低密度区间: 下限" type="INTEGER"/> <column name="low_end" remarks="低密度区间: 上限" type="INTEGER"/> <column name="medium_start" remarks="中密度区间: 下限" type="INTEGER"/> <column name="medium_end" remarks="中密度区间: 上限" type="INTEGER"/> <column name="high_start" remarks="高密度区间: 下限" type="INTEGER"/> <column name="high_end" remarks="高密度区间: 上限" type="INTEGER"/> </createTable> </changeSet>
<changeSet id="create_geohash_6" author="Aaron" runOnChange="true"> <preConditions onError="MARK_RAN" onFail="MARK_RAN"> <not> <tableExists tableName="geohash_6"/> </not> </preConditions>
<createTable remarks="GeoHash6信息" tableName="geohash_6"> <column name="id" type="INTEGER" remarks="主键id" autoIncrement="true" startWith="1" incrementBy="1"> <constraints primaryKey="true" nullable="false"/> </column> <column name="geohash" remarks="GeoHash6数据" type="VARCHAR(255)"/> <column name="center_lng" remarks="中心点经度" type="VARCHAR(255)"/> <column name="center_lat" remarks="中心点纬度" type="VARCHAR(255)"/> <column name="max_lng" remarks="最大经度" type="VARCHAR(255)"/> <column name="max_lat" remarks="最大纬度" type="VARCHAR(255)"/> <column name="min_lng" remarks="最小经度" type="VARCHAR(255)"/> <column name="min_lat" remarks="最小纬度" type="VARCHAR(255)"/> <column name="is_hz_edge" remarks="是否为边界" type="BOOLEAN"/> </createTable> </changeSet>
<changeSet id="add tag" author="Aaron"> <tagDatabase tag="1.0"/> </changeSet>
</databaseChangeLog>
|
- changeSet标签:出于便于阅读的角度考虑,每个changeSet每次只包含对一张表的修订操作。同时,对于已执行过changeSet一般情况下不应做任何修改
- runOnChange属性:用于控制每次运行changeSet时,如果本次changeSet发生修改是否重新执行。其默认值为false,当本次changeSet发生修改不会执行变更,而是会发出错误以提醒发生了意外修改。其原理是通过比对changeSet的MD5校验和、存储在DATABASECHANGELOG表中的MD5SUM进行 判定的。典型地对于存储过程场景而言,该属性一般设置为true。这样每次对历史changeSet进行修改后,都需要Liquibase重新执行该changeSet以保证修改生效
- preConditions标签:控制数据库变更的先决条件。如果先决条件满足要求,则会执行该标签后相应的数据库变更;如果先决条件在执行过程抛出异常,则行为由onError属性控制;如果先决条件不满足要求,则行为由onFail属性控制;
- onFail、onError属性:preConditions标签的onFail、onError属性可用的取值有:
- CONTINUE:跳过该changeSet、会在下次更新时再次尝试。继续执行changeLog
- HALT:停止执行整个changeLog。这也是默认值
- MARK_RAN:跳过该changeSet同时将其标记为已执行。继续执行changeLog
- WARN:发出警告并继续执行changeSet、changeLog
- tagDatabase:对本次版本的数据库修订打标签
至此当我们启动SpringBoot项目后,即可发现数据库不仅包含了我们期望的业务表,还新增了两张Liquibase相关的表——DATABASECHANGELOG、DATABASECHANGELOGLOCK
而对于DATABASECHANGELOGLOCK锁表而言,如果某记录的LOCKED字段为1,则表示该锁被占有了。故在Liquibase锁无法正常释放时,可能会导致无法创建表,这时可通过手动置零来释放锁
生成ChangeLog
liquibase-maven-plugin可以帮助我们直接地从数据库中创建、生成相应的ChangeLog文件,配置如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| <build> <plugins> <plugin> <groupId>org.liquibase</groupId> <artifactId>liquibase-maven-plugin</artifactId> <version>3.6.3</version> <configuration> <outputChangeLogFile>${basedir}/src/main/resources/db/generate/changeLog.xml</outputChangeLogFile> <driver>com.mysql.jdbc.Driver</driver> <url>jdbc:mysql://localhost:3306/db1?useSSL=false</url> <username>root</username> <password>123456</password> <dropFirst>false</dropFirst> <verbose>true</verbose> <logging>debug</logging> <promptOnNonLocalDatabase>false</promptOnNonLocalDatabase> <outputFileEncoding>UTF-8</outputFileEncoding> <propertyFileWillOverride>true</propertyFileWillOverride> </configuration> </plugin> </plugins> </build>
|
操作、效果如下所示