前言

介绍springboot快速集成liquibase使用

简介:liquibase

liquibase是一个数据库变更的版本控制工具。项目中通过liquibase解析用户编写的liquibase的配置文件,生成sql语句,并执行和记录。执行是根据记录确定sql语句是否曾经执行过,和配置文件里的预判断语句确定sql是否执行。

解决痛点:
1. 数据库升级脚本和项目代码版本管理分离的,不能跟着项目版本走。
2. 传统的数据升级脚本需要运维手动执行, 不能自动化就没法配合容器化部署和微服务多项目的趋势
3. 定义了一种数据脚本,不支持多数据库部署(mysql/orcale/progressSQL) 同样都是关系型数据库,升级脚本还得多款。

针对上述痛点,liuquibase怎么做的:
1. 数据库变化内容记录在changelog文件, 我们按项目不同版本记录对应版本changelog中, 这样数据库变化版本就关联项目版本,脚本提交因为在同一个代码仓库,有git记录了关联业务需求。另外changelog中每个变化也可以记录作者,这样关联研发同学。因此什么需求,做了什么改动,谁改的就一目了然。
2. 项目启动自动执行changelog文件, 已经执行过不会重复执行,自带执行锁。保证集群微服务启动, 只有一个项目执行数据库脚本任务。
3. changelog使用是一种中间态的描述语言定义来定义数据变化,(xml.json yaml多种格式可选),liquibase会根据实际连接数据库类型,换成对应的数据操作语句,完全透明。只要定义一次就好。有点类似java"一处编写,到处运行",

一句话: Track, version, and deploy database changes

  • 官网: https://liquibase.org/

实践1.最小化启用liquibase

1. maven依赖添加

		<parent>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-parent</artifactId>
			<version>2.1.7.RELEASE</version>
		</parent>
		
		<!-- 项目引用第三方jar包 全局版本信息 -->
		<properties>
			<!-- mysql-->
			<mysql-connector-java.version>8.0.27</mysql-connector-java.version>
		</properties>
		
		<!-- liquibase管理升级脚本(org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration 自动装配)-->
		<dependency>
			<groupId>org.liquibase</groupId>
			<artifactId>liquibase-core</artifactId>
		</dependency>
		
		<!--mysql jdbc驱动 -->
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>${mysql-connector-java.version}</version>
		</dependency>

2. application.yaml配置changelog-master.xml

引入liquibase的包后,springboot通过spring-boot-autoconfigure包中org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration 默认自动启用配置,只要配置数据库表配置描述文件即可

spring:
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://192.168.100.50:3306/test?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true
    username: root
    password: 123456
  liquibase:
    change-log: classpath:db/liquibase/changelog-master.xml

3. changelog-master.xml管理changelog文件

<?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.8.xsd">
    <include file="classpath:db/liquibase/changelog/changelog_init.xml"/>
    <include file="classpath:db/liquibase/changelog/changelog_v1.0.xml"/>
</databaseChangeLog>

这里扫描文件src/main/resources/db/liquibase/changelog目录,为不同版本建立不同的changelog文件
在这里插入图片描述

  • changelog_init.xml 项目初始搭建脚步
  • changelog_v1.0 当前版本新增的数据库结构变动
  • changelog_v1.1 …

4. 项目表初始化changelog_init.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: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/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.5.xsd">

    <changeSet author="myron" id="account.createTable">
        <createTable tableName="account" remarks="账号表">
            <!--设置id自增 起始位置从10000 每次加1-->
            <column name="id" remarks="账户ID" type="bigint" autoIncrement="true" incrementBy="1" startWith="10000">
                <constraints primaryKey="true" nullable="false"/>
            </column>
            <!--用户名增加唯一索引-->
            <column name="username" remarks="用户名" type="VARCHAR(32)">
                <constraints nullable="false" unique="true" uniqueConstraintName="uniq_username"/>
            </column>
            <column name="password" remarks="密码" type="VARCHAR(32)"/>
            <column name="name" remarks="姓名" type="VARCHAR(20)"/>
            <column name="sex" remarks="性别" type="CHAR(1)"/>
            <column name="phone" remarks="手机" type="VARCHAR(100)"/>
            <column name="email" remarks="邮件" type="VARCHAR(100)"/>
            <column name="create_time" remarks="创建时间" type="datetime"/>
            <column name="update_time" remarks="修改时间" type="datetime"/>

        </createTable>
    </changeSet>

    <changeSet id="account.addUniqueConstraint_email" author="myron">
        <addUniqueConstraint tableName="account" columnNames="email" constraintName="uniq_email"></addUniqueConstraint>
    </changeSet>

</databaseChangeLog>

注意! MySQL从5.7版本开始,取消了为自增列设置增量(incrementBy)的功能。在5.7版本之前,可以使用AUTO_INCREMENT=n来设置自增列的起始值和增量。但是在5.7版本中,MySQL开始忽略AUTO_INCREMENT子句中的增量值,始终将增量设置为1。因此,在更高版本的MySQL中(包括5.7和之后的版本),不再允许指定自增列的增量。 因此Liquibase中incrementBy=“1” 需要去掉(更新于2024-04-08, 为啥要去掉参考附录)

5. 启动运行

项目启动后会自动生成 liquibase用于记录版本信息的配置表, 同时根据changelog生成业务数据表
在这里插入图片描述

实践2.逆向生成changelog.xml文件

场景一:在一些情况下,要把项目从一种关系型数据库切替换成另一种,但是不同的数据库的表建表语句是有差异的这时候可以巧妙利用liquibase的逆向工程来实现.
如: postgressql > changlog.xml -> mysql

场景二:备份当前项目库的建表信息

1. maven插件配置:liquibase-maven-plugin

从已有项目数据库表生成,通过liquibase的maven插件

			<!--mvn liquibase:generateChangeLog (mysql表反向生成liquibase的xml配置)-->
			<plugin>
				<groupId>org.liquibase</groupId>
				<artifactId>liquibase-maven-plugin</artifactId>
				<version>3.5.1</version>
				<configuration>
					<!--properties文件路径,该文件记录了数据库连接信息等
					<propertyFile>src/main/resources/liquibase.properties</propertyFile>
					-->
					<propertyFileWillOverride>true</propertyFileWillOverride>
					<!--生成文件的路径-->
					<outputChangeLogFile>src/main/resources/db/liquibase/changelog/changelog_init.xml</outputChangeLogFile>
					<!--要连接库配置信息 -->
					<driver>com.mysql.jdbc.Driver</driver>
                    <url>jdbc:mysql://192.168.100.50:3306/demo_aop_log?useUnicode=true&amp;characterEncoding=utf-8</url>
                    <username>root</username>
                    <password>123456</password>

				</configuration>
			</plugin>

2. maven命令执行:反向生成changelog

mvn liquibase:generateChangeLog

效果(反向生成的似乎把自增id的位置,丢失了)

<?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: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/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.5.xsd">
    <changeSet author="Administrator (generated)" id="1645106952625-1" objectQuotingStrategy="QUOTE_ALL_OBJECTS">
        <createTable tableName="account">
            <column autoIncrement="true" name="id" type="BIGINT">
                <constraints primaryKey="true"/>
            </column>
            <column name="username" remarks="用户名" type="VARCHAR(32)"/>
            <column name="password" remarks="密码" type="VARCHAR(32)"/>
            <column name="name" remarks="姓名" type="VARCHAR(20)"/>
            <column name="sex" remarks="性别" type="CHAR(1)"/>
            <column name="phone" remarks="手机" type="VARCHAR(100)"/>
            <column name="email" remarks="邮件" type="VARCHAR(100)"/>
            <column name="create_time" remarks="创建时间" type="datetime(6)"/>
            <column name="update_time" remarks="修改时间" type="datetime(6)"/>
        </createTable>
    </changeSet>
</databaseChangeLog>

使用规范(团队开发)

  1. ChangeSet必须填写author。
  2. Liquibase禁止对业务数据进行sql操作。
  3. 所有表,列要加remarks进行注释。
  4. 已经执行过的ChangeSet严禁修改。
  5. 不要随便升级项目liquibase版本,特别是大版本升级。不同版本
    ChangeSet MD5SUM的算法不一样

常用操作(持续总结…)

一 自增主键设置

从10000起算目的是为了.保留10000以内可以手动创建特殊账号留有余地.

            <!--设置id自增 起始位置从10000 每次加1-->
            <column name="id" remarks="账户ID" type="bigint" autoIncrement="true" incrementBy="1" startWith="10000">
                <constraints primaryKey="true" nullable="false"/>
            </column>

二 属性列加索引

  1. 建表时定义索引列
       <!--用户名增加唯一索引-->
            <column name="username" remarks="用户名" type="VARCHAR(32)">
                <constraints nullable="false" unique="true" uniqueConstraintName="uniq_username"/>
            </column>

uniqueConstraintName=“uniq_username” 为索引名称

团队开发时候索引可以定个规约,示例

(1)单张表中索引数量不超过5个。
(2)单个索引中的字段数不超过5个。
(3)索引名必须全部使用小写。
(4)非唯一索引按照“idx_字段名称[_字段名称]”进用行命名。例如idx_name。
(5)唯一索引按照“uniq_字段名称[_字段名称]”进用行命名。例如uniq_username。
(6)组合索引建议包含所有字段名,过长的字段名可以采用缩写形式。例如idx_name_sex

  1. 建表后补充索引
    <changeSet id="account.addUniqueConstraint_email" author="myron">
        <addUniqueConstraint tableName="account" columnNames="email" constraintName="uniq_email"></addUniqueConstraint>
    </changeSet>

三 初始化导入数据

使用loadData加载csv数据,可以做一些项目初始化数据的导入

    <!--loadData:加载 csv 文件到已存在的表中-->
    <changeSet id="account.loadData" author="myron">
        <loadData tableName="account" file="db/liquibase/csv/account.csv" >
        </loadData>
    </changeSet>

account.csv

"id","username","password","name","sex","phone","email","create_time","update_time"
"10000","zhangsan","123456","张三","","17223333333","aaa@qq.com","2022-2-17 17:55:45","2022-2-25 17:56:06"
"10001","lisi","1234","李四","","12345678912","lisi@qq.com","2022-2-14 17:56:02","2022-2-21 17:56:11"

效果(时间导入好像有点问题,不确认是不是格式有问题.得再研究下)
在这里插入图片描述
经过排查是数据有问题日期天"2022-2-17 17:55:45" 需要补0 为 “2022-02-17 17:55:45” 可以正常导入

四 自动重建功能

liquibase提供spring.liquibase.drop-first=true(默认false) 项目每次重启后, 会删除所有表后重新初始化。个人开发阶段或者系统设计初期1.0版本,表设计不稳定,需要针对changeSet反复修改, 不用担心冲突.(这一点是违反上面规范的,团队开发最好不要开启,代码提交后禁止修改changeSet,所以仅限个人开发使用)

另外使用场景可以作用演示系统。使用liquibase初始化并通过上面csv初始化必要数据。用户体验时候可以随意折腾测试。搞坏了,重启即可。啥?重启有点麻烦,那就在线初始化。(友情提示:正式环境禁止提交该接口代码,数据安全大于一切

@RestController
@RequestMapping("/liquibase")
public class LiquiBaseTestController {
    @Autowired
    private SpringLiquibase springLiquibase;

    @PostMapping("initLiquibase")
    public ApiResult<String> runLiquibase() throws LiquibaseException {
        springLiquibase.setDropFirst(true);
        springLiquibase.afterPropertiesSet();
        springLiquibase.setDropFirst(false);
        return ApiResult.success("手动执行liquibase成功");
    }
}    

附录

mysql为啥去掉自增量?

取消自增列增量的目的可能是为了简化语法并提高数据库的一致性。自增列的增量通常应该是1,因此将其固定为1可以避免不必要的混淆和错误。此外,取消自增列的增量也可以简化MySQL内部的实现。

因此,当使用较新版本的MySQL时,您不需要再为自增列指定增量值,因为它们始终会按1递增。在Liquibase或其他数据库变更管理工具中,应该避免为自增列设置增量,以避免出现验证失败的错误

参考文档

  1. 官网
  2. LiquiBase中文学习指南
    • 重点参考学习
  3. liquibase介绍
  4. mysql索引命名规范_mysql使用规范-索引规范
  5. liquibase使用技巧及最佳实践
    • 这篇写的使用技巧,总结的不错
  6. Liquibase 数据库版本管理工具:3. changeSet 变更集详解
Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐