介绍springboot快速集成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
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>2.1.7.RELEASEversion>
parent>
<properties>
<mysql-connector-java.version>8.0.27mysql-connector-java.version>
properties>
<dependency>
<groupId>org.liquibasegroupId>
<artifactId>liquibase-coreartifactId>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>${mysql-connector-java.version}version>
dependency>
引入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
<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文件
<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="账号表">
<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>
项目启动后会自动生成 liquibase用于记录版本信息的配置表, 同时根据changelog生成业务数据表
场景一:在一些情况下,要把项目从一种关系型数据库切替换成另一种,但是不同的数据库的表建表语句是有差异的这时候可以巧妙利用liquibase的逆向工程来实现.
如: postgressql > changlog.xml -> mysql
场景二:备份当前项目库的建表信息
从已有项目数据库表生成,通过liquibase的maven插件
<plugin>
<groupId>org.liquibasegroupId>
<artifactId>liquibase-maven-pluginartifactId>
<version>3.5.1version>
<configuration>
<propertyFileWillOverride>truepropertyFileWillOverride>
<outputChangeLogFile>src/main/resources/db/liquibase/changelog/changelog_init.xmloutputChangeLogFile>
<driver>com.mysql.jdbc.Driverdriver>
<url>jdbc:mysql://192.168.100.50:3306/demo_aop_log?useUnicode=true&characterEncoding=utf-8url>
<username>rootusername>
<password>123456password>
configuration>
plugin>
mvn liquibase:generateChangeLog
效果(反向生成的似乎把自增id的位置,丢失了)
<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>
从10000起算目的是为了.保留10000以内可以手动创建特殊账号留有余地.
<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>
(1)单张表中索引数量不超过5个。
(2)单个索引中的字段数不超过5个。
(3)索引名必须全部使用小写。
(4)非唯一索引按照“idx_字段名称[_字段名称]”进用行命名。例如idx_age_name。
(5)唯一索引按照“uniq_字段名称[_字段名称]”进用行命名。例如uniq_age_name。
(6)组合索引建议包含所有字段名,过长的字段名可以采用缩写形式。例如idx_age_name_add
<changeSet id="account.addUniqueConstraint_email" author="myron">
<addUniqueConstraint tableName="account" columnNames="email" constraintName="uniq_email">addUniqueConstraint>
changeSet>
使用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","[email protected]","2022-2-17 17:55:45","2022-2-25 17:56:06"
"10001","lisi","1234","李四","","12345678912","[email protected]","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” 可以正常导入
个人开发阶段,可以使用spring.liquibase.drop-first=true删除表后重建. 可以针对changeSet反复修改, 不用担心冲突.(这一点是违反上面规范的,团队开发最好不好开启,代码提交后禁止修改changeSet,所以仅限个人开发使用)