SpringBoot使用Liquibase最佳实践
Liquibase 问题随着项目的发展,一个项目中的代码量会非常庞大,同时数据库表也会错综复杂。如果一个项目使用了 Liquibase 对数据库结构进行管理,越来越多的问题会浮现出来。ChangeSet 文件同时多人在修改,自己的 ChangeSet 被改掉,甚至被删除掉。开发人员将 ChangeSet 添加到已经执行过的文件中,导致执行顺序出问题。开发人员擅自添加对业务...
Liquibase 问题
随着项目的发展,一个项目中的代码量会非常庞大,同时数据库表也会错综复杂。如果一个项目使用了 Liquibase 对数据库结构进行管理,越来越多的问题会浮现出来。
ChangeSet 文件同时多人在修改,自己的 ChangeSet 被改掉,甚至被删除掉。
开发人员将 ChangeSet 添加到已经执行过的文件中,导致执行顺序出问题。
开发人员擅自添加对业务数据的修改,其它环境无法执行并报错。
ChangeSet 中 SQL 包含 schema 名称,导致其它环境 schema 名称变化时,ChangeSet 报错。
开发人员不小心改动了已经执行过的 ChangeSet,在启动时会报错。
Liquibase 基本规范
ChangeSet id 使用 [任务 ID]-[日期]-[序号],如 T100-20181009-001
ChangeSet 必须填写 author
Liquibase 禁止对业务数据进行 sql 操作
使用
<sql>
时,禁止包含 schema 名称Liquibase 禁止使用存储过程
所有表,列要加 remarks 进行注释
已经执行过的 ChangeSet 严禁修改。
不要随便升级项目 liquibase 版本,特别是大版本升级。不同版本 ChangeSet MD5SUM 的算法不一样。
其它数据库规范不再赘述。
1. <?xml version="1.0" encoding="UTF-8"?>
2. <databaseChangeLog
3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4. xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
5. xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">
6. <changeSet id="T100-20181009-001" author="markfredchen" >
7. <createTable table>
8. <column >
9. <constraints nul/>
10. </column>
11. <column >
12. <constraints nul/>
13. </column>
14. ...
15. </createTable>
16. </changeSet>
17. </databaseChangeLog>
有效文件管理
使用 Liquibase 中提供<include file="xxx"/>
tag,可以将 ChangeSet 分布在不同文件中。同时<include/>
支持多级引用。基于此功能可以对项目中的 ChangeSet 进行有效管理。推荐使用以下规范进行管理。
根据发布进行管理
每个发布新建一个文件夹,所有发布相关的 ChangeSet 文件以及数据初始化文件,均放在些文件夹中。
每个发布新建一个 master.xml。此 master.xml 中,include 本次发布需要执行的 ChangeSet 文件
根据开发小组独立 ChangeSet 文件 (可选)
根据功能独立 ChangeSet 文件。例如 user.xml, company.xml
1. `resources`
2. `|-liquibase`
3. `|-user`
4. `| |- master.xml`
5. `| |- release.1.0.0`
6. `| | |- release.xml`
7. `| | |- user.xml -- 用户相关表ChangeSet`
8. `| | |- user.csv -- 用户初始化数据`
9. `| | |- company.xml -- 公司相关表ChangeSet`
10. `| |- release.1.1.0`
11. `| | |- release.xml`
12. `| | |- ...`
模块化管理
当项目变得庞大之后,一个服务可能包含的功能模块会越来越多。此时大家会想尽办法进行模块拆分,逐步进行微服务化。然而在面对错综复杂的 Liquibase ChangeSet 就会无从下手。针对这种将来可能会面对的问题,项目初期就对 Liquibase 进行模块化管理,将在未来带来很大收益。首先说明一下 Spring Boot 中 Liquibase 默认是如何执行以及执行结果。
在启动时,LiquibaseAutoConfiguration 会根据默认配置初始化 SpringLiquibase
SpringLiquibase.afterPropertiesSet() 中执行 ChangeSet 文件
第一次跑 ChangeSets 的时候,会在数据库中自动创建两个表
databasechangelog
和databasechangeloglock
因此我们可以认为一个 SpringLiquibase 执行为一个模块。
引入多模块管理时,基于上节文件管理规范,我们基于模块管理再做下调整。
1. `resources`
2. `|-liquibase`
3. `|-user`
4. `| |- master.xml`
5. `| |- release.1.0.0`
6. `| | |- release.xml`
7. `| | |- user.xml -- 用户相关表ChangeSet`
8. `| | |- user.csv -- 用户初始化数据`
9. `| | |- company.xml -- 公司相关表ChangeSet`
10. `| |- release.1.1.0`
11. `| | |- release.xml`
12. `| | |- ...`
13. `|- order`
14. `| |- master.xml`
15. `| |- release.1.0.0`
16. `| | |- ...`
当有一天我们需要把订单模块拆分成独立服务时,我们只需要将模块相关的 ChangeSet 文件迁出来。即可完成数据结构的拆分。
那如何在一个 Spring Boot 运行多个 SpringLiquibase 呢?需要对代码进行以下调整。
禁用 Spring Boot 自动运行 Liquibase。
当以下配置被启用时,Spring Boot AutoConfigure 会使用默认配置初始化名为 springLiquibase 的 Bean。然后我们不对其进行配置,Spring Boot 启动时会报错。
1. `# application.properties`
2. `# spring boot 2以上`
3. `spring.liquibase.enabled=false`
4. `# spring boot 2以下`
5. `liquibase.enabled=false`
Spring Boot 配置 Liquibase Bean
配置两个 SpringLiquibase Bean,Bean 名称分别为 userLiquibase 和 orderLiqubase。
1. @Configuration
2. public class LiquibaseConfiguration() {
4. /**
5. * 用户模块Liquibase
6. */
7. @Bean
8. public SpringLiquibase userLiquibase(DataSource dataSource) {
9. SpringLiquibase liquibase = new SpringLiquibase();
10. // 用户模块Liquibase文件路径
11. liquibase.setChangeLog("classpath:liquibase/user/master.xml");
12. liquibase.setDataSource(dataSource);
13. liquibase.setShouldRun(true);
14. liquibase.setResourceLoader(new DefaultResourceLoader());
15. // 覆盖Liquibase changelog表名
16. liquibase.setDatabaseChangeLogTable("user_changelog_table");
17. liquibase.setDatabaseChangeLogLockTable("user_changelog_lock_table");
18. return liquibase;
19. }
20. /**
21. * 订单模块Liquibase
22. */
23. @Bean
24. public SpringLiquibase orderLiquibase() {
25. SpringLiquibase liquibase = new SpringLiquibase();
26. liquibase.setChangeLog("classpath:liquibase/order/master.xml");
27. liquibase.setDataSource(dataSource);
28. liquibase.setShouldRun(true);
29. liquibase.setResourceLoader(new DefaultResourceLoader());
30. liquibase.setDatabaseChangeLogTable("order_changelog_table");
31. liquibase.setDatabaseChangeLogLockTable("order_changelog_lock_table");
32. return liquibase;
33. }
34. }
来源链接:
https://www.bbsmax.com/A/VGzlKEQwdb/
更多推荐
所有评论(0)