当前位置: 首页 > news >正文

Spring Boot中如何使用Flyway进行数据库迁移

        在本文中,我们将了解如何使用 Flyway 来管理 Spring Boot 应用程序中的 SQL 数据库架构。

        在本文中,我们将了解如何使用 Flyway 来管理Spring Boot应用程序中的SQL 数据库架构。
Flyway是一个数据库迁移工具,它提供迁移历史和回滚的功能,并允许我们将应用程序的数据库模式相关层与数据库实体层分离。

应用程序设置

我们将使用的 Spring Boot 应用程序可以使用此Spring Initializr链接生成。它包含所有必要的依赖项。
下载应用程序并解决依赖关系后,我们将创建一个名为spring-boot-flyway的新 Postgres 数据库,并配置应用程序以连接到它。

清单 2.1 application.properties

spring.datasource.url=jdbc:postgresql://localhost:5432/spring-boot-flyway
spring.datasource.username=demo
spring.datasource.password=demo

默认情况下,Flyway 会在类路径中的db/migration/目录中搜索包含用于管理数据库表和记录的 SQL 语句的迁移文件。 

对于旧版本的库,我们可能需要在resources/db/migration/ 中创建一个名为.keep的空文本文件,以确保该目录在应用程序启动期间被编译并可用,以避免错误。

完成此操作后,我们现在可以启动应用程序并且它应该成功运行。

基本用法

Flyway 的工作方式是,我们在resources/db/migration目录中创建一个迁移文件,Spring Boot 会自动执行迁移脚本,因为我们已经在第 2 节中将 Flyway 依赖项添加到了类路径中。

清单3.1 V1__Users.sql

CREATE TABLE IF NOT EXISTS users
(id    SERIAL,email VARCHAR(200) NOT NULL,name  VARCHAR(200) NOT NULL,PRIMARY KEY (id)
);

让我们花一点时间来检查一下清单 3.1 中的代码片段。文件名V1__Users.sql遵循一定的约定:

  • “ V ”表示这是版本化迁移。
  • V后面的“ 1 ”是实际版本号。它也可以是“ V1_1 ”,这将转换为版本 1.1。
  • 后面是分隔符“ __ ”(两个下划线)。这会将版本信息与迁移文件的名称(在本例中为Users )分开。
  • 最后一部分“ .sql ”是扩展名;因此,该文件包含一个简单的 SQL 语句。

此时,重新启动应用程序将在数据库中创建用户表。此外,我们可以看到还有另一个我们没有显式创建的表 - Flyway_schema_history 

Flyway_schema_history由 Flyway 本身用来跟踪已应用的迁移如果该表丢失,Flyway 将假设我们是第一次初始化数据库,并按照版本号的顺序运行所有迁移。

Flyway_schema_history表存在时,Flyway 将仅应用之前未应用过的较新的迁移文件。这意味着,为了添加新表,我们只需创建具有更新版本号的更新的迁移文件并重新启动应用程序。

除了使用 SQL 之外,我们还可以使用Java编写迁移脚本。在Java迁移风格中,我们的迁移文件是Java类,必须扩展抽象BaseJavaMigration类并实现migrate方法。

IDE 通常不希望 Java 类位于resources目录中,因此我们将在src/main/java中创建一个名为db/migration的新包非常重要的是要知道这个新包db/migration应该位于src/main/jav目录中。

让我们创建一个新的 Java 迁移来添加新表:

清单 3.2 V2__Posts.java 

public class V2__Posts extends BaseJavaMigration {@Overridepublic void migrate(Context context) throws Exception {var sql = """CREATE TABLE posts (id SERIAL,author_id INT NOT NULL,post TEXT NOT NULL,created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,PRIMARY KEY (id));""";try(var statement = context.getConnection().createStatement()) {statement.execute(sql);}}
}

与 SQL 文件相比,使用 Java 迁移的优点是我们可以添加使用普通 SQL 无法实现的自定义逻辑、条件和验证。例如,我们可以检查另一个表是否存在或从环境中获取某些值等。

正如您现在可能猜到的那样,是的,可以在同一个代码库中混合 SQL 和 Java 风格的迁移,只要我们确保两种情况下的 Flyway 位置相同。

Flyway配置和定制

到目前为止,我们一直在使用默认的 Flyway 行为。我们可以进一步调整 Flyway 以满足我们的需求。例如,我们可以更改迁移文件的默认位置、配置数据库架构(也称为表空间)、将 SQL 迁移前缀从“V”更改为我们想要的任何内容等等。

在下面的配置中,我们配置了迁移文件所在的路径并禁用清理数据库(即删除所有表)以防止在生产环境中意外使用。

清单4.1 application.properties:

spring.flyway.locations=classpath:migrations
spring.flyway.clean-disabled=true

该键下还有其他可配置属性spring.flyway,我们可以使用它们来微调库的行为。另外,我们可以查阅Flyway 文档页面以供参考。

飞行路线回调

Flyway为我们提供了配置回调的能力,这些回调可以在迁移过程的不同阶段调用。回调机制是在迁移生命周期的不同阶段执行某些操作的便捷方法。 

假设我们有一些默认数据想要在应用程序启动时播种。我们可以简单地创建一个支持该AFTER_MIGRATE事件的回调。

清单 5.1 FlywayDatabaseSeeder.java:

public class FlywayDatabaseSeeder implements Callback {@Overridepublic boolean supports(Event event, Context context) {return event.name().equals(Event.AFTER_MIGRATE.name());}@Overridepublic void handle(Event event, Context context) {try(var statement = context.getConnection().createStatement()) {var ADMIN_EMAIL = "superadmin@example.com";var checkQuery = "SELECT id FROM users WHERE email = %s".formatted(ADMIN_EMAIL);statement.execute(checkQuery);ResultSet resultSet = statement.getResultSet();resultSet.last();//return if the seeder has already been executedif(resultSet.getRow() >= 0) return;var sql = """INSERT INTO users (email, name) VALUES('%s', 'Super Admin')""".formatted(ADMIN_EMAIL);statement.execute(sql);} catch (SQLException e) {throw new RuntimeException(e);}}@Overridepublic boolean canHandleInTransaction(Event event, Context context) {return true;}@Overridepublic String getCallbackName() {return FlywayDatabaseSeeder.class.getName();}
}

在上面的清单中,在supports方法中,我们声明只应针对AFTER_MIGRATE事件执行此回调,并且在handle方法中,我们概述了插入默认超级管理员用户(如果尚不存在)的逻辑。

在这之前,我们需要在 SpringBoot 中向 Flyway 注册回调类。我们通过创建一个FlywayMigrationStrategybean 来做到这一点。

清单 5.2 SpringBootFlywayApplication.java 

@Bean
public FlywayMigrationStrategy flywayMigrationStrategy() {return (flywayOld) -> {/*Update the existing autoconfigured Flywaybean to include our callback class*/Flyway flyway = Flyway.configure().configuration(flywayOld.getConfiguration()).callbacks(new FlywayDatabaseSeeder()).load();flyway.migrate();};
}

rg.flywaydb.core.api.callback.Event枚举中还有其他事件 ,我们可以配置Callback类来支持。例如,您可以有一个回调来支持该AFTER_MIGRATE_ERROR事件并发送 Slack 通知来提醒工程师。

技巧和窍门

在本地环境中进行开发时,您可以从Flyway_schema_history表中删除迁移条目。

下次启动应用程序时,您删除其历史记录的迁移将再次执行。这样,您可以更正错误或更新架构,同时仍在本地计算机上进行开发,而无需删除整个数据库。

此外,在 SpringBoot 中,您可以控制 Flyway 在应用程序启动时何时执行迁移脚本。例如,假设我们不希望在本地环境中自动执行迁移。我们可以执行以下操作:

清单6.1 SpringBootFlywayApplication.java:

@Bean
public FlywayMigrationStrategy flywayMigrationStrategy(@Value("${spring.profiles.active}") String activeProfile) {return (flywayOld) -> {/*Update the existing autoconfigured Flywaybean to include our callback class*/Flyway flyway = Flyway.configure().configuration(flywayOld.getConfiguration()).callbacks(new FlywayDatabaseSeeder()).load();if(!"local".equalsIgnoreCase(activeProfile)) {flyway.migrate();}};
}

结论

使用数据库迁移工具的优点之一是它使数据库架构成为应用程序代码库的一部分。由于应用程序中有一个中心参考点,因此可以更轻松地跟踪数据库随时间的变化。

相关文章:

Spring Boot中如何使用Flyway进行数据库迁移

在本文中,我们将了解如何使用 Flyway 来管理 Spring Boot 应用程序中的 SQL 数据库架构。 在本文中,我们将了解如何使用 Flyway 来管理Spring Boot应用程序中的SQL 数据库架构。 Flyway是一个数据库迁移工具,它提供迁移历史和回滚的功能&…...

web在线编辑器(vue版)

目录 前言一、monaco-editor1、源码2、体积优化 二、ace-editor?1、源码2、体积优化 总结 前言 提示:这里可以添加本文要记录的大概内容: 例如:随着人工智能的不断发展,机器学习这门技术也越来越重要,很多…...

【论文阅读】 Model Sparsity Can Simplify Machine Unlearning

Model Sparsity Can Simplify Machine Unlearning 背景主要内容Contribution Ⅰ:对Machine Unlearning的一个全面的理解Contribution Ⅱ:说明model sparsity对Machine Unlearning的好处Pruning方法的选择sparse-aware的unlearning framework Experiments…...

Spring Clould 部署 - Docker

视频地址:微服务(SpringCloudRabbitMQDockerRedis搜索分布式) 初识Docker-什么是Docker(P42,P43) 微服务虽然具备各种各样的优势,但服务的拆分通用给部署带来了很大的麻烦。 分布式系统中&…...

linux--链表动态创建

头插法: 核心代码: s->next head->next; head->next s; 尾插法 核心代码: tail head; s->next NULL; tail->next s; tail s; 当用头插法依次插入值分别为1,2,3,4,5的结点后, 单链表顺序为: he…...

iBooker 布客技术评论 20230818

一、程序员自检手册 为了避免焦虑,你首先需要做的就是梳理你的业务: (1)你所在的行业是轻资产还是重资产? 重资产就是人绕着机器转,创业需要买一大堆设备。如果是重资产,赶紧换一个。 &…...

CK-A60180、CK-B1542、CK-L3095单向离合器

CK-A1542、CK-A1747、CK-A2052、CK-A2652、CK-A3072、CK-A3580、CK-A4090、CK-A45100、CK-A450110、CK-A60130、CK-A65140、CK-A70150、CK-A75160、CK-A80170、CK-A1250、CK-A1855、CK-A2060、CK-A2563、CK-A2563T、CK-A2870、CK-A3080T、CK-A3585、CK-A35100、CK-A35140、CK-A…...

单因素多变量方差分析

多变量方差分析:是对多个独立变量是否受单个或多个因素影响而进行的方差分析。它不仅能够分析多个因素对观测变量的独立影响,更能够分析多个因素的交互作用能否对观测变量产生影响。本章以单因素多变量分析为例,即一个分组变量和多个欲分析的…...

Python Web:Django、Flask和FastAPI框架对比

原文:百度安全验证 Django、Flask和FastAPI是Python Web框架中的三个主要代表。这些框架都有着各自的优点和缺点,适合不同类型和规模的应用程序。 1. Django: Django是一个全功能的Web框架,它提供了很多内置的应用程序和工具&am…...

【CI/CD】Rancher K8s

Rancher & K8s Rancher 和 K8s 的关系是什么?K8s 全称为 Kubernetes,它是一个开源的,用于管理云平台中多个主机上的容器化的应用。而 Rancher 是一个完全开源的企业级多集群 Kubernetes 管理平台,实现了 Kubernetes 集群在混合…...

nodejs 之 express 实现下载网络图片并上传到七牛云对象存储oss空间

为方便阅读,本文将所有逻辑放在一个函数里,可根据自己的情况拆分。 安装依赖 在项目根目录下运行以下命令安装依赖 npm install express qiniu axios业务逻辑 在项目根目录下创建一个名为 app.js 的文件,并添加以下内容 const express re…...

综合能源系统(7)——综合能源综合评估技术

综合能源系统关键技术与典型案例  何泽家,李德智主编 综合能源系统是多种能源系统非线性耦合的、多时间与空间尺度耦合的“源-网-荷一储”一体化系统,通过能源耦合、多能互补,能够实现能源的高效利用,并提高新能源的利用水平。对…...

【JS 线性代数算法之向量与矩阵】

线性代数算法 一、向量的加减乘除1. 向量加法2. 向量减法3. 向量数乘4. 向量点积5. 向量叉积 二、矩阵的加减乘除1. 矩阵加法2. 矩阵减法3. 矩阵数乘4. 矩阵乘法 常用数学库 线性代数是数学的一个分支,用于研究线性方程组及其解的性质、向量空间及其变换的性质等。在…...

配置 yum/dnf 置您的系统以使用默认存储库

题目 给系统配置默认存储库,要求如下: YUM 的 两 个 存 储 库 的 地 址 分 别 是 : ftp://host.domain8.rhce.cc/dvd/BaseOS ftp://host.domain8.rhce.cc/dvd/AppStream vim /etc/yum.repos.d/redhat.repo [base] namebase baseurlftp:/…...

Docker容器与虚拟化技术:Docker资源控制、数据管理

目录 一、理论 1.资源控制 2.Docker数据管理 二、实验 1.Docker资源控制 2.Docker数据管理 三、问题 1.docker容器故障导致大量日志集满,造成磁盘空间满 2、当日志占满之后如何处理 四、总结 一、理论 1.资源控制 (1) CPU 资源控制 cgroups&#xff0…...

python生成器有几种写法,python生成器函数例子

大家好,小编来为大家解答以下问题,python生成器有几种写法,python生成器函数例子,今天让我们一起来看看吧! 本文部分参考:Python迭代器,生成器–精华中的精华 https://www.cnblogs.com/deeper/p…...

动态动画弹窗样式css

点击下载图片素材 html <div class"popWin"> </div> <div class"popPic"><div class"popWinBtn01">查看证书</div><div class"wintips01">恭喜您已完成训练营学习任务&#xff0c;荣誉证书已发放…...

数据生成 | MATLAB实现WGAN生成对抗网络数据生成

数据生成 | MATLAB实现WGAN生成对抗网络数据生成 目录 数据生成 | MATLAB实现WGAN生成对抗网络数据生成生成效果基本描述程序设计参考资料 生成效果 基本描述 1.WGAN生成对抗网络&#xff0c;数据生成&#xff0c;样本生成程序&#xff0c;MATLAB程序&#xff1b; 2.适用于MATL…...

PHP实现每日蛋白质摄入量计算器

1.laravel 路由 //每日蛋白质摄入计算器Route::get(api/protein/intake, FormulaControllerproteinIntakeCal); 2.代码 /*** 每日蛋白质摄入计算器*/public function proteinIntakeCal(){$number intval($this->request(number));$goalFactor array(0.8, 1.16, 0.8, 1.16,…...

vue elment 表格内表单校验代码

<p v-if"scope.row.id">{{ scope.row.bidderCode }}</p><el-form-itemclass"formitem"v-else:prop"bidderCode scope.row.id":rules"getValidationRules(投标人/供应商代码, scope.row.id)"><el-input v-model&…...

如何在Stream流中分组统计

上面是今天碰到需求,之前就做过类似的分组统计,这个相对来说比较简单,统计的也少,序号和总预约人数这两部分交给前端了,不需要由后端统计,后端统计一下预约日期和检查项目和预约人数就行; Overridepublic List<ItemStatisticsVo> statistics(ItemStatisticsModel itemSta…...

windows程序基础

一、windows程序基础 1. Windows程序的特点 1&#xff09;用户界面统一、友好 2&#xff09;支持多任务:允许用户同时运行多个应用程序(窗口) 3&#xff09;独立于设备的图形操作 使用图形设备接口( GDI, Graphics Device Interface )屏蔽了不同硬件设备的差异&#…...

【LeetCode】买卖股票的最佳时机最多两次购买机会

买卖股票的最佳时机 题目描述算法分析程序代码 链接: 买卖股票的最佳时机 题目描述 算法分析 程序代码 class Solution { public:int maxProfit(vector<int>& prices) {int n prices.size();vector<vector<int>> f(n,vector<int>(3,-0x3f3f3f))…...

【C++ 记忆站】命名空间

文章目录 命名空间概念命名空间的定义1、正常的命名空间定义2、命名空间可以嵌套3、同一个工程中允许存在多个相同名称的命名空间,编译器最后会合成同一个命名空间中 命名空间的使用1、加命名空间名称及作用域限定符2、使用using将命名空间中某个成员引入3、使用using namespac…...

《离散数学及其应用(原书第8版)》ISBN978-7-111-63687-8 第11章 11.1.3 树的性质 节 第664页的例9说明

《离散数学及其应用&#xff08;原书第8版&#xff09;》ISBN978-7-111-63687-8 第11章 11.1.3 树的性质 节 第664页的定理3的引申 定理3 带有i个内点的m叉树含有nmi1个顶点 见本人博文 内点定义不同的讨论 如果对于一个m叉正则树&#xff0c;即任意分支节点的儿子恰好有m个&am…...

【云原生】K8S存储卷:PV、PVC详解

目录 一、emptyDir存储卷二、hostPath存储卷三、nfs共享存储卷四、PVC 和 PV4.1 NFS使用PV和PVC4.2创建动态PV 一、emptyDir存储卷 容器磁盘上的文件的生命周期是短暂的&#xff0c;这就使得在容器中运行重要应用时会出现一些问题。首先&#xff0c;当容器崩溃时&#xff0c;ku…...

谈谈IP地址和子网掩码的概念及应用

个人主页&#xff1a;insist--个人主页​​​​​​ 本文专栏&#xff1a;网络基础——带你走进网络世界 本专栏会持续更新网络基础知识&#xff0c;希望大家多多支持&#xff0c;让我们一起探索这个神奇而广阔的网络世界。 目录 一、IP地址的概念 二、IP地址的分类 1、A类 …...

vue2 如何监听数组的变化

在Vue 2中&#xff0c;底层是通过重写数组的原型方法来实现对数组变化的监听。具体来说&#xff0c;Vue 2使用了一个名为Observer的类来劫持数组的原型方法&#xff0c;使其在调用这些方法时能够触发相应的变化通知。 当Vue 2初始化一个响应式对象时&#xff0c;如果对象是一个…...

CSS中的transform属性有哪些值?并分别描述它们的作用。

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ translate()⭐ rotate()⭐ scale()⭐ skew()⭐ matrix()⭐ scaleX() 和 scaleY()⭐ rotateX()、rotateY() 和 rotateZ()⭐ translateX() 和 translateY()⭐ skewX() 和 skewY()⭐ perspective()⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&…...

vue3跳转页面后 海康监控实例不销毁

第一个页面是这样的 跳转到新的页面 只有海康的监控没有消失 使用控制台审查元素也审查不到 解决方法&#xff1a;在vue3的销毁周期把海康的监控销毁掉 import { reactive, onDeactivated} from "vue"; const state reactive({oWebControl: null as any, //监控绑…...