Liquibase问题

随着项目的发展,一个项目中的代码量会非常庞大,同时数据库表也会错综复杂。如果一个项目使用了Liquibase对数据库结构进行管理,越来越多的问题会浮现出来。

  1. ChangeSet文件同时多人在修改,自己的ChangeSet被改掉,甚至被删除掉。
  2. 开发人员将ChangeSet添加到已经执行过的文件中,导致执行顺序出问题。
  3. 开发人员擅自添加对业务数据的修改,其它环境无法执行并报错。
  4. ChangeSet中SQL包含schema名称,导致其它环境schema名称变化时,ChangeSet报错。
  5. 开发人员不小心改动了已经执行过的ChangeSet,在启动时会报错。

Liquibase基本规范

  1. ChangeSet id使用[任务ID]-[日期]-[序号],如 T100-20181009-001
  2. ChangeSet必须填写author
  3. Liquibase禁止对业务数据进行sql操作
  4. 使用<sql>时,禁止包含schema名称
  5. Liquibase禁止使用存储过程
  6. 所有表,列要加remarks进行注释
  7. 已经执行过的ChangeSet严禁修改。
  8. 不要随便升级项目liquibase版本,特别是大版本升级。不同版本ChangeSet MD5SUM的算法不一样。

其它数据库规范不再赘述。

<?xml version="1.0" encoding="UTF-8"?>
<databaseChangeLog
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">
<changeSet id="T100-20181009-001" author="markfredchen" >
<createTable tableName="demo_user" remarks="用户表">
<column name="id" type="bigint" remarks="用户ID,主键">
<constraints nullable="false" primaryKey="true" primaryKeyName="pk_demo_user_id"/>
</column>
<column name="username" type="varchar(100)" remarks="用户名">
<constraints nullable="false"/>
</column>
...
</createTable>
</changeSet>
</databaseChangeLog>

有效文件管理

使用Liquibase中提供<include file="xxx"/>tag,可以将ChangeSet分布在不同文件中。同时<include/>支持多级引用。
基于此功能可以对项目中的ChangeSet进行有效管理。推荐使用以下规范进行管理。

根据发布进行管理

  1. 每个发布新建一个文件夹,所有发布相关的ChangeSet文件以及数据初始化文件,均放在些文件夹中。
  2. 每个发布新建一个master.xml。此master.xml中,include本次发布需要执行的ChangeSet文件
  3. 根据开发小组独立ChangeSet文件(可选)
  4. 根据功能独立ChangeSet文件。例如user.xml, company.xml
resources
|-liquibase
|-user
| |- master.xml
| |- release.1.0.0
| | |- release.xml
| | |- user.xml -- 用户相关表ChangeSet
| | |- user.csv -- 用户初始化数据
| | |- company.xml -- 公司相关表ChangeSet
| |- release.1.1.0
| | |- release.xml
| | |- ...

模块化管理

当项目变得庞大之后,一个服务可能包含的功能模块会越来越多。此时大家会想尽办法进行模块拆分,逐步进行微服务化。然而在面对错综复杂的Liquibase ChangeSet就会无从下手。
针对这种将来可能会面对的问题,项目初期就对Liquibase进行模块化管理,将在未来带来很大收益。
首先说明一下Spring Boot中Liquibase默认是如何执行以及执行结果。

  1. 在启动时,LiquibaseAutoConfiguration会根据默认配置初始化SpringLiquibase
  2. SpringLiquibase.afterPropertiesSet()中执行ChangeSet文件
  3. 第一次跑ChangeSets的时候,会在数据库中自动创建两个表databasechangelog和databasechangeloglock

因此我们可以认为一个SpringLiquibase执行为一个模块。

引入多模块管理时,基于上节文件管理规范,我们基于模块管理再做下调整。

resources
|-liquibase
|-user
| |- master.xml
| |- release.1.0.0
| | |- release.xml
| | |- user.xml -- 用户相关表ChangeSet
| | |- user.csv -- 用户初始化数据
| | |- company.xml -- 公司相关表ChangeSet
| |- release.1.1.0
| | |- release.xml
| | |- ...
|- order
| |- master.xml
| |- release.1.0.0
| | |- ...

当有一天我们需要把订单模块拆分成独立服务时,我们只需要将模块相关的ChangeSet文件迁出来。即可完成数据结构的拆分。

那如何在一个Spring Boot运行多个SpringLiquibase呢?需要对代码进行以下调整。

  1. 禁用Spring Boot自动运行Liquibase。

当以下配置被启用时,Spring Boot AutoConfigure会使用默认配置初始化名为springLiquibase的Bean。然后我们不对其进行配置,Spring Boot启动时会报错。

# application.properties
# spring boot 2以上
spring.liquibase.enabled=false
# spring boot 2以下
liquibase.enabled=false
  1. Spring Boot配置Liquibase Bean

配置两个SpringLiquibase Bean,Bean名称分别为userLiquibase和orderLiqubase。

@Configuration
public class LiquibaseConfiguration() { /**
* 用户模块Liquibase
*/
@Bean
public SpringLiquibase userLiquibase(DataSource dataSource) {
SpringLiquibase liquibase = new SpringLiquibase();
// 用户模块Liquibase文件路径
liquibase.setChangeLog("classpath:liquibase/user/master.xml");
liquibase.setDataSource(dataSource);
liquibase.setShouldRun(true);
liquibase.setResourceLoader(new DefaultResourceLoader());
// 覆盖Liquibase changelog表名
liquibase.setDatabaseChangeLogTable("user_changelog_table");
liquibase.setDatabaseChangeLogLockTable("user_changelog_lock_table");
return liquibase;
}
/**
* 订单模块Liquibase
*/
@Bean
public SpringLiquibase orderLiquibase() {
SpringLiquibase liquibase = new SpringLiquibase();
liquibase.setChangeLog("classpath:liquibase/order/master.xml");
liquibase.setDataSource(dataSource);
liquibase.setShouldRun(true);
liquibase.setResourceLoader(new DefaultResourceLoader());
liquibase.setDatabaseChangeLogTable("order_changelog_table");
liquibase.setDatabaseChangeLogLockTable("order_changelog_lock_table");
return liquibase;
}
}

Spring Boot使用Liquibase最佳实践的更多相关文章

  1. spring boot 使用及最佳实践

    第一部分,spring boot 文档 Spring boot的使用 使用maven进行构建 用户可以通过继承spring-boot-starter-parent来获取默认的依赖. l  默认java ...

  2. Spring Boot 16 条最佳实践

    Spring Boot是最流行的用于开发微服务的Java框架.在本文中,我将与你分享自2016年以来我在专业开发中使用Spring Boot所采用的最佳实践.这些内容是基于我的个人经验和一些熟知的Sp ...

  3. 【Spring Cloud】Spring Cloud之整合Spring Cloud Bus以及最佳实践

    一.整合步骤 1)加入Maven坐标 <!-- actuator监控模块 --> <dependency> <groupId>org.springframework ...

  4. Spring Boot消息队列应用实践

    消息队列是大型复杂系统解耦利器.本文根据应用广泛的消息队列RabbitMQ,介绍Spring Boot应用程序中队列中间件的开发和应用. 一.RabbitMQ基础 1.RabbitMQ简介 Rabbi ...

  5. spring boot + mybatis + druid配置实践

    最近开始搭建spring boot工程,将自身实践分享出来,本文将讲述spring boot + mybatis + druid的配置方案. pom.xml需要引入mybatis 启动依赖: < ...

  6. Spring Boot开发MongoDB应用实践

    本文继续上一篇定时任务中提到的邮件服务,简单讲解Spring Boot中如何使用MongoDB进行应用开发. 上文中提到的这个简易邮件系统大致设计思路如下: 1.发送邮件支持同步和异步发送两种 2.邮 ...

  7. Spring Boot WebFlux 快速入门实践

    02:WebFlux 快速入门实践 Spring Boot 2.0 spring.io 官网有句醒目的话是: BUILD ANYTHING WITH SPRING BOOT Spring Boot ( ...

  8. Spring Boot Admin简介及实践

    问题 在若干年前的单体应用时代,我们可以相对轻松地对整个业务项目进行健康检查.指标监控.配置管理等等项目治理.如今随着微服务的发展,我们将大型单体应用按业务模型进行划分,以此形成众多小而自治的微服务, ...

  9. Spring Boot 配置文件 – 在坑中实践

    摘要: 原创出处 www.bysocket.com 「泥瓦匠BYSocket 」欢迎转载,保留摘要,谢谢!   『 仓廪实而知礼节,衣食足而知荣辱 - 管仲 』   本文提纲 一.自动配置 二.自定义 ...

随机推荐

  1. 第二届中国“AI+”创新创业大赛完美收官,京东云赛道硕果累累

    聚焦南京产业发展核心诉求,京东云携手南京政府构建的"平台+生态+赋能"的产业体系,搭建产业创新云平台,以人工智能产业创新链要素补齐为核心,围绕"研.产.供.销.服&quo ...

  2. c# 用户控件,usercontrol,自定义控件属性

    1.C#用户控件的使用 2.拖动添加:画面上如需多个usercontrol,添加TableLayoutPanel,然后在工具箱中找到usercontrol,拖到相应框中 3.代码添加:主窗口中有多个T ...

  3. LeJOS下eclipse通过USB连接EV3

    适用情况:在eclipse安装好LeJOS插件后,再通过USB连接EV3. 第一:更新驱动 在<设备管理器-网络适配器>下更新RNDIS/Ethernet Gadget,电脑需要先连接EV ...

  4. 2020/2/3 PHP代码审计之PHP弱类型

    0x00 简介 php中有两种比较的符号 == 与 === <?php 2 $a = $b ; 3 $a===$b ; 4 ?> === 在进行比较的时候,会先判断两种字符串的类型是否相等 ...

  5. Window NodeJs安装

    1.下载NodeJs 官网下载地址:http://nodejs.cn/download/ ​ 2.安装 双击,全程next安装. 安装完成,在cmd下面执行查看版本命令,命令如下 C:\Users\A ...

  6. CF #610Div2 B2.K for the Price of One (Hard Version) (dp解法 && 贪心解法)

    原题链接:http://codeforces.com/contest/1282/problem/B2题目大意:刚开始有 p 块钱,商店有 n 件物品,你每次可以只买一件付那一件的钱,也可以买 k 件只 ...

  7. MYSQL连接不上100061错误

    有界面的情况下启动MYSQL 无界面 https://blog.csdn.net/qq_22233621/article/details/72673176 参考

  8. 零基础程序员入门Linux系统 !如何快速恢复系统?

    新手在学习Linux系统的时候,难免会遇到命令输错,或系统出错的难题.那么如何快速解决呢?本文就先给你一个后悔药,让你快速备份并恢复Linux系统.本文将以Ubuntu为例,在这之前,你需要一台服务器 ...

  9. solr集群的搭建

    solrCloud 昨天随手写了个solr单机版的搭建,今天准备写一个solr集群的搭建!1.solr集群只要环境配置正确还是比较简单的环境:CentOS-6.4-i386-bin-DVD1.isoj ...

  10. UML-如何画常用UML交互图?

    1.生命线框图(参与者) 2.消息表达式