最近,就是昨天,在项目上线前一天,因为本次上线涉及到修改字段的问题,本来以往都是jpa实体类加属性,然后自动生成表字段,然后手动将数据库字段迁移,然后领导就突然要求本次上线数据库修改,必须通过Liquibase来管理。时间只有一天,对没错,一天,在此之前是一个没听过Liquibase的状态的我,心中十万个策马奔腾。
本来,大概看了一下博客,以为这个东西很容易搞定,也给老大承诺了,一天内可以整合进项目,然后,然后我就草了,经历了入职以来最不浑水摸鱼的一天,虽然在整合,部署,上线踩了很多坑【两点上线完】,但是感觉这样紧张的节奏,学习效率还是很高的,下面简单分享我的整合过程,因为我也看了不少Liquibase的博客,总体感觉一是太杂乱,二是没有完整的一篇springboot+gradle+liqubase的博客,我希望通过这个实战经历简单的让大家上手Liquibase。
不用看那些maven管理工具里面那些添加liquibase插件之类的东西,入门的话,那些东西只能更让我们晕头转向
// https://mvnrepository.com/artifact/org.liquibase/liquibase-core
runtimeOnly('org.liquibase:liquibase-core:3.6.2') {
exclude(module: 'logback-classic')
}
runtimeOnly("com.inspur.cloud:liquibase-schema:3.6")
spring:
#数据库相关的配置
datasource:
url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC&useSSL=false
username: root
password: root
# jpa配置
jpa:
show-sql: false
hibernate:
ddl-auto: none
database-platform: org.hibernate.dialect.MySQL5InnoDBDialect
# liquibase配置
liquibase:
enabled: true
change-log: "classpath:/db/changelog/db.changelog-master.yaml"
contexts: dev
上面配置中药注意四个点:
- spring.liquibase.change-log 配置文件的路径,默认值为 classpath:/db/changelog/db.changelog-master.yaml
- spring.liquibase.check-change-log-location 检查 change log的位置是否存在,默认为true.
- spring.liquibase.contexts 用逗号分隔的运行环境列表。
- spring.liquibase.default-schema 默认数据库 schema
- spring.liquibase.drop-first 是否先 drop schema(默认 false)
- spring.liquibase.enabled 是否开启 liquibase(默认为 true)
- spring.liquibase.password 数据库密码
- spring.liquibase.url 要迁移的JDBC URL,如果没有指定的话,将使用配置的主数据源.
- spring.liquibase.user 数据用户名
- spring.liquibase.rollback-file 执行更新时写入回滚的 SQL文件
配置完上面这些东西,直接启动项目,启动项目会发现类似下面的报错信息,不要怕,就是没有找到liquibase的主配置文件:
Error creating bean with name 'org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration$LiquibaseConfiguration'
Cannot find changelog location: class path resource [config/liquibase/master_changelog.xml] (please add changelog or check your Liquibase configuration)
这个时候要注意了,这个master_changelog.xml文件的位置就取决于上面第三步中application.yml中liquibase.change_log的配置
此时,你的项目中,如果你只希望通过这一个配置文件作为liquibase的配置脚本,那也就够了,可以直接将你的sql,或者xml写在master_changelog.xml中就可以了。
但是,如果是公司项目的话,你后期可能会有多个这种配置文件,你可以通过分类,来将每次的liquibase脚本放在每个文件夹里,在我的项目中,是以月份来区分的,比如后期这种脚本多了之后,项目会是这个样子:
每个文件夹里都是一个小的liquibase配置脚本
databaseChangeLog:
- include:
file: db/changelog/eip/mysql/t201905/2019050901-ddl-init-zerah.xml
- include:
file: db/changelog/eip/mysql/t201905/2019050901-dml-change-sbwName_and_sbwId-zerah.xml
再来看一下项目结构:
大概意思我想你应该可以看懂,就是引入了两个文件,这两个文件就称它是liquibase的配置脚本
大概就是 数据库表结构的操作是ddl,数据增删改就是dml
2019050901-ddl-init-zerah.xml
eip表加入sbw_id字段
eip表加入sbw_id字段
2019050901-dml-change-sbwName_and_sbwId-zerah.xml
UPDATE eip eip1, eip eip2
SET eip1.sbw_id = eip2.shared_band_width_id where eip1.eip_id =eip2.eip_id;
UPDATE eip eip1, eip eip2
SET eip1.sbw_id = eip2.shared_band_width_id where eip1.eip_id =eip2.eip_id;
仔细看上面两个配置脚本中的context,我想应该大致明白context的作用了吧,就是以此来区分不同环境对不同changeset的引入
每个更改集都用 “id”属性和“author”属性唯一标识。“作者”属性可以最大限度地减少重复的可能性。
liquibase将每个更改集视为要应用于数据库的原子更改。通常最好只在更改集中包含一个更改
其实现在,启动项目,liquibase已经管理起来你对数据库的操作了,具体做的操作就是上面两个配置文件中配置的内容
检查你的数据库
你可以看到数据库现在额外创建了另外两个表:“databasechangelog”和“databasechangeloglock”。
现在你已经糊里糊涂的在项目中整合上了liquibase,现在我们再来结合其他博客感受一下liquibase
Liquibase是一个用于跟踪、管理和应用数据库变化的开源的数据库重构工具。它将所有数据库的变化(包括结构和数据)都保存在XML文件中,便于版本控制
在日常的项目开发中,开发团队经常将数据库和应用程序视为单独的实体,这样就导致了数据库团队与应用开发团队分离造成团队之间信息交流不畅,信息交流不及时,这种情况通常表现为下面几种行为
手工变更数据库
不能与团队的其他成员分享数据库变更
使用不一致的方法变更数据库或数据
使用低效的手工方法管理数据库版本之间的变更
上面的几种行为都是我们在实际开发中遇到的问题,不仅效率低而且出错的机率也高,就算是老司机也会翻车
随着新特性添加到了应用程序中,经常需要变更数据库的结构或修改表约束。LiquiBase 提了超过 30 种数据库重构支持(参见 IBM参考资料)。本节将介绍 4 种重构:添加列(Add Column)、删除列(Drop Column)、创建表(Create Table)和操作数据。
在项目的开始,几乎不可能考虑到数据库中的所有列。而有时候,用户要求新的特性 —例如为存储在系统中的信息收集更多的数据 —这就要求添加新的列。
清单 4 使用 LiquiBase addColumn重构,向数据库中的 distributor表添加了一个列:
假如在以后几个版本中,您想要删除在清单 4 添加的 phonenumber列。只需要调用 dropColumn重构,如清单 5 所示:
向数据库添加一个新表也是常见的数据库重构。清单 6 创建了一个新表 distributor,定义了列、约束和默认值:
在应用了结构性数据重构后(例如添加列和创建表),通常需要向受重构影响的表中插入数据。此外,可能需要修改查找表(或其他类型的表)中的现有数据。清单 7 展示了如何使用一个 LiquiBase 变更集插入数据:
您应该编写用于操作数据的 SQL 脚本,因为使用 LiquiBase XML 变更集限制很多。有时候使用 SQL 脚本向数据库应用大量的变更会简单一些。LiquiBase 也可以支持这些情景。清单 8 调用变更集中的 insert-distributor-data.sql来插入 distributor表数据: