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

spring boot整合flyway实现数据的动态维护

1、简单介绍一下flyway

Flyway 是一款开源的数据库版本控制工具,主要用于管理数据库结构的变更(如创建表、修改字段、插入数据等)。它通过跟踪和执行版本化的迁移脚本,帮助团队实现数据库变更的自动化。接下来简单介绍一下flyway的工作流程:

1.1、 初始化阶段

  • 检查元数据表
    Flyway 首先检查目标数据库中是否存在 flyway_schema_history 表(默认表名称,也可以自定义历史表名称)。

    • 不存在:自动创建该表,用于记录迁移历史

    • 已存在:读取已有迁移记录

千万不要手动的修改历史表的任何数据,不然肯定会导致版本管理错误。

1.2、 迁移扫描

  • 脚本加载
    扫描配置的 locations 路径(默认 classpath:db/migration),识别两类脚本:

    • 版本化迁移脚本V 开头)

    • 可重复迁移脚本R 开头)

1.3、校验阶段

  • 校验 Checksum
    对比已执行脚本的 checksum 与本地文件的 checksum

    • 若已执行脚本的 checksum 发生变化 → 抛出错误(防止篡改历史脚本)

    • 校验通过 → 进入迁移阶段

1.4、 迁移执行

  • 版本化迁移
    按版本号顺序执行所有 未应用 的 V 前缀脚本,且 仅执行一次

  • 可重复迁移
    按文件名顺序执行 R 前缀脚本,当脚本内容变化时 重新执行

1.5、 更新元数据

每个成功执行的脚本会被记录到 flyway_schema_history 表,包含:

版本号

脚本名称

checksum

执行时间

执行状态

如图就是一个默认的历史表中数据。

在这里详细解释一个flyway中的两种字母开头的执行脚本的不同;

V 开头 vs R 开头脚本的区别

1. 版本化迁移脚本(V 前缀)

  • 命名规则
    V<Version>__<Description>.sql(例如 V1.2__Create_User_Table.sql

    • Version唯一不可变的版本号(建议使用语义化版本,如 1.0.1

    • Description:人类可读的描述(使用下划线分隔单词)

  • 核心特性

    • 一次性执行:每个脚本仅执行一次

    • 顺序敏感:按版本号顺序依次执行

    • 内容不可变:已执行的脚本内容不可修改(否则校验失败)

  • 典型场景

    • 创建/修改表结构

    • 新增索引或约束

    • 一次性数据迁移(如初始化基础数据)

2. 可重复迁移脚本(R 前缀)

  • 命名规则
    R__<Description>.sql(例如 R__Update_Product_View.sql

    • 没有版本号

    • Description:描述脚本作用(按字母顺序排序执行)

  • 核心特性

    • 重复执行:脚本内容变化时自动重新执行

    • 顺序依赖:按文件名字母顺序执行

    • 内容可变:允许修改后重新应用

  • 典型场景

    • 维护视图(View)或存储过程(Stored Procedure)

    • 更新静态数据(如多环境差异化配置)

    • 重建索引或物化视图

关键对比总结

特性V 前缀脚本R 前缀脚本
执行次数仅一次内容变化时重复执行
版本号必须唯一且递增无版本号
内容修改禁止修改(会导致校验失败)允许修改(触发重新执行)
执行顺序按版本号顺序按文件名字母顺序
适用场景结构变更、一次性操作可重复逻辑、数据维护

最佳实践建议

  1. 版本化脚本 (V)

    • 使用语义化版本(如 V1.2.3

    • 每个脚本完成一个独立的变更任务

    • 禁止修改已提交到代码仓库的 V 脚本

  2. 可重复脚本 (R)

    • 用于维护视图、存储过程等易变对象

    • 通过文件名控制执行顺序(如 R__01_ViewA.sqlR__02_ViewB.sql

    • 谨慎修改生产环境的 R 脚本(可能触发全量更新)

  3. 混合使用策略

    • 用 V 脚本管理表结构变更

    • 用 R 脚本管理视图和存储过程

示例:

db/migration/
├── V1.0__Create_Tables.sql
├── V1.1__Add_Indexes.sql
└── R__Update_Views.sql
  1. 校验保护

    • 生产环境务必启用 validate-on-migrate: true

    • 开发环境可开启 flyway.validate-migration-naming: true 强制命名校验

通过合理使用 V 和 R 脚本,可以实现数据库变更的 原子性 和 可追溯性,同时适应不同场景的灵活性需求。

2、使用spring boot项目整合flyway

2.1、新创建一个spring boot项目,并导入一些初始的依赖;

 <dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.flywaydb</groupId><artifactId>flyway-core</artifactId><!-- 无需指定版本(Spring Boot 已管理) --></dependency><!--  druid连接池  --><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.2.18</version></dependency><!--    MySQL--><dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</artifactId></dependency><!-- 无需指定版本(Spring Boot 已管理) --><dependency><groupId>org.flywaydb</groupId><artifactId>flyway-mysql</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>3.0.3</version></dependency></dependencies>

需要注意的一点是,spring官方自动管理的flyway的版本,所以我们只需要指定spring的版本就自动会兼容合适的flyway版本,我的spring boot版本为3.3.9

我们主要使用到的依赖有三个:

flyway-core:flyway的核心依赖

flyway-mysql:指定数据库的类型

mybatis-spring-boot-starter: 数据源的自动配置,也可以是其他的依赖坐标。不一定要是mybatis,如JDBC、JPA等都可以

2.2、配置相应的yml配置文件

spring:datasource:type: com.alibaba.druid.pool.DruidDataSourcedriver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/testflyway?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTCusername: rootpassword: 123456flyway:enabled: truelocations: ["classpath:db/migration"]  #  修正为数组格式table: flyway_schema_historybaseline-on-migrate: true  # 必须启用(处理已有表场景)sql-migration-prefix: "V"sql-migration-separator: "__"sql-migration-suffixes: [".sql"]  #  数组格式
logging:level:org.flywaydb: TRACE  # 输出最详细日志

我们只需要配置一些flyway的属性,就可以直接使用flyway了。

2.3、编写相应的sql执行语句,并且存放在固定的文件地址

-- 创建用户表
CREATE TABLE IF NOT EXISTS user (id INT AUTO_INCREMENT PRIMARY KEY,username VARCHAR(50) NOT NULL UNIQUE,email VARCHAR(100) NOT NULL,created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);-- 初始数据插入
INSERT INTO user (username, email) VALUES('admin', 'admin@example.com'),('user1', 'user1@example.com');

我这里就创建了一张数据表,并且插入了一些数据;

将SQL脚本放在合适的位置:

注意SQL脚本的存放位置不是乱放的,要符合我们之前在yml配置文件中书写的配置,SQL脚本的名称也不是随便取得,要符合flyway的命名规范。

2.4、运行spring boot项目

我们配置好了这些之后,就可以直接启动spring boot项目了。如果你是第一次启动项目,flyway会自动扫描相应文件夹下的SQL脚本,并在你的数据库中建立一个历史记录表 flyway_schema_history。要特别注意的是我们千万不要手动的修改这张表中的任何数据,flyway就是根据这张历史记录表来进行SQL脚本的执行等等一系列操作。

我们可以直接在控制台中看到flyway已经顺利的执行我们相应的SQL脚本

我们现在可以连接一下数据库来看看是否正确

 

可以看到数据库中已经有了相应的数据表,并且数据表中已经有了一些初始数据了

这个是我们第一次启动spring boot项目时自动执行的SQL脚本。那么等我们第二次启动时,flyway还是会扫描相应的SQL脚本,同时查询 flyway_schema_history 历史表,来判断SQL脚本要不要执行。当我们在此运行spring boot项目:

我们在控制台的日志中可以很清楚的看到flyway的执行过程。

3、总结

以上,就是我们使用spring boot整合flyway来进行数据库的版本管理。总体来说是非常简单的,我们只需要一些简单的配置和遵守一些flyway的命名规定就可以直接使用flyway了。这也是spring官方一直在努力推行的

约定大于配置,配置大于编码

当然,flyway的功能还有很多,这篇文章也只是初步帮你认识一下flyway。并且使用spring boot来简单的使用flyway的基本功能,但总的来说,我们几乎可以只通过一些配置文件中属性来使用flyway的绝大部分功能,一下我整理了一些常用的flyway属性,供大家参考:

spring:flyway:# 基础配置enabled: true                       # 是否启用 Flyway,默认 trueurl: jdbc:mysql://localhost:3306/db # 覆盖默认数据库连接(可选)user: root                          # 覆盖默认数据库用户(可选)password: root                      # 覆盖默认数据库密码(可选)# 脚本管理locations:                          # 迁移脚本路径(默认 classpath:db/migration)- classpath:db/migrations- filesystem:/opt/migrationsencoding: UTF-8                     # 脚本文件编码,默认 UTF-8sql-migration-prefix: V             # 版本迁移脚本前缀,默认 "V"repeatable-sql-migration-prefix: R  # 可重复迁移脚本前缀,默认 "R"sql-migration-separator: __         # 脚本名称分隔符,默认双下划线sql-migration-suffixes:             # 脚本后缀列表,默认 [".sql"]- .sql- .pgsql# 迁移规则schemas: public                     # Flyway 管理的 schema 列表(逗号分隔)table: flyway_history               # 元数据表名,默认 "flyway_schema_history"baseline-on-migrate: false          # 迁移时自动执行基线(默认 false)baseline-version: 1                 # 基线版本号,默认 "1"baseline-description: Initial Setup # 基线描述target: latest                      # 目标版本(默认最新版本,可用版本号如 "3.1")out-of-order: false                 # 是否允许乱序执行迁移(默认 false)validate-on-migrate: true           # 迁移时校验脚本(默认 true)ignore-missing-migrations: false    # 忽略缺失的迁移记录(默认 false)# 占位符配置placeholder-replacement: true       # 启用占位符替换(默认 true)placeholders:                       # 自定义占位符键值对key1: value1key2: value2# 高级配置clean-on-validation-error: false    # 校验失败时自动执行 clean(危险!默认 false)connect-retries: 3                  # 连接失败重试次数(默认 0)lock-retry-count: 50                # 获取锁的重试次数(默认 50)group: false                        # 将相同版本的迁移合并为单个事务(默认 false)mixed: false                        # 是否允许混合 DDL 和 DML(默认 false)skip-default-callbacks: false       # 跳过默认回调(默认 false)skip-default-resolvers: false       # 跳过默认解析器(默认 false)init-sqls:                          # 获取连接后立即执行的 SQL 语句- SET ROLE 'myuser'# 多环境配置示例
---
spring:profiles: prodflyway:url: jdbc:mysql://prod-db:3306/prod_dblocations:- "classpath:db/migration/common"- "classpath:db/migration/prod"ignore-migration-patterns: "*:pending"

关键配置说明:

  1. 基础配置:默认会复用 spring.datasource 配置,需要覆盖时单独指定

  2. 脚本管理:通过前缀/后缀/路径控制脚本识别规则

  3. 迁移规则:控制基线、校验、执行顺序等核心行为

  4. 生产环境注意事项:

    • clean-on-validation-error 应始终保持 false

    • out-of-order 需谨慎启用

    • 建议明确指定 target 版本控制生产环境迁移

  5. 最佳实践:

    • 使用 classpath 和 filesystem 组合路径管理脚本

    • 通过 placeholders 实现环境差异化配置

    • 启用校验确保迁移安全

可以通过 flyway.validateMigrationNaming 配置项(默认 false)开启严格的脚本命名校验,建议开发环境开启。

flyway的官网地址为:https://flywaydb.org/

你有如果想了解更多有关flyway的信息,可以直接访问官网

相关文章:

spring boot整合flyway实现数据的动态维护

1、简单介绍一下flyway Flyway 是一款开源的数据库版本控制工具&#xff0c;主要用于管理数据库结构的变更&#xff08;如创建表、修改字段、插入数据等&#xff09;。它通过跟踪和执行版本化的迁移脚本&#xff0c;帮助团队实现数据库变更的自动化。接下来简单介绍一下flyway…...

通往 AI 之路:Python 机器学习入门-线性代数

2.1 线性代数&#xff08;机器学习的核心&#xff09; 线性代数是机器学习的基础之一&#xff0c;许多核心算法都依赖矩阵运算。本章将介绍线性代数中的基本概念&#xff0c;包括标量、向量、矩阵、矩阵运算、特征值与特征向量&#xff0c;以及奇异值分解&#xff08;SVD&…...

Matlab中的均值函数mean

今天调了一个代码里的bug&#xff0c;根源居然是mean函数的使用细节没留意到~ 具体来说&#xff0c;写一个类似k均值聚类那样的程序&#xff0c;交替迭代&#xff0c;其中有一部是使用mean求一堆向量的均值&#xff0c;这些向量存在一个矩阵里&#xff0c;每行对应一个向量。若…...

数据结构知识学习小结

一、动态内存分配基本步骤 1、内存分配简单示例&#xff1a; 个人对于示例的理解&#xff1a; 定义一个整型的指针变量p&#xff08;着重认为它是一个“变量”我觉得可能会更好理解&#xff09;&#xff0c;这个变量用来存地址的&#xff0c;而不是“值”&#xff0c;malloc函…...

高精算法的用法及其优势

高精度问题是指当数据的位数非常大&#xff08;超出标准数据类型的范围&#xff09;时&#xff0c;如何进行计算和存储的问题。常见场景包括大整数的加、减、乘、除、取模等操作。以下是解决高精度问题的常用方法与技巧&#xff1a; 一、数据存储 数组存储 用整型数组存储&am…...

【Spring AOP】_切点类的切点表达式

目录 1. 根据方法签名匹配编写切点表达式 1.1 具体语法 1.2 通配符表达规范 2. 根据注解匹配编写切点表达式 2.1 实现步骤 2.2 元注解及其常用取值含义 2.3 使用自定义注解 2.3.1 编写自定义注解MyAspect 2.3.2 编写切面类MyAspectDemo 2.3.3 编写测试类及测试方法 在…...

多线程-定时任务线程池源码

定时任务线程池 ScheduledThreadPoolExecutor&#xff0c;可以执行定时任务的线程池。这里学习它的基本原理。 定时任务线程池&#xff0c;和普通线程池不同的地方在于&#xff0c;它使用一个延迟队列&#xff0c;延迟队列使用最小堆作为它的数据结构&#xff0c;它会按照任务…...

初次使用 IDE 搭配 Lombok 注解的配置

前言 在 Java 开发的漫漫征程中&#xff0c;我们总会遇到各种提升效率的工具。Lombok 便是其中一款能让代码编写变得更加简洁高效的神奇库。它通过注解的方式&#xff0c;巧妙地在编译阶段为我们生成那些繁琐的样板代码&#xff0c;比如 getter、setter、构造函数等。然而&…...

云服数据存储接口:CloudSever

云服数据存储接口&#xff1a;CloudSever 迷你世界 更新时间: 2024-04-28 19:09:10 具体函数名及描述如下&#xff1a; 序号 函数名 函数描述 1 setOrderDataBykey(...) 设置排行榜中指定键的数值 2 removeOrderDataByKey(...) 删除排行榜中指定键的数值 …...

关于 QPalette设置按钮背景未显示出来 的解决方法

若该文为原创文章&#xff0c;转载请注明原文出处 本文章博客地址&#xff1a;https://hpzwl.blog.csdn.net/article/details/146047054 长沙红胖子Qt&#xff08;长沙创微智科&#xff09;博文大全&#xff1a;开发技术集合&#xff08;包含Qt实用技术、树莓派、三维、OpenCV…...

上传文件到对象存储是选择前端还是后端

对于云上对象存储的上传方式选择&#xff08;前端直传或后端代理上传&#xff09;&#xff0c;需综合考虑安全性、性能、成本、业务需求等因素。 1. 推荐前端直传的场景 适用条件&#xff1a; 大文件上传&#xff08;如视频、大型数据集&#xff09;高并发场景&#xff08;如…...

mysql下载与安装

一、mysql下载&#xff1a; MySQL获取&#xff1a; 官网&#xff1a;www.mysql.com 也可以从Oracle官方进入&#xff1a;https://www.oracle.com/ 下载地址&#xff1a;https://downloads.mysql.com/archives/community/ 选择对应的版本和对应的操作系统&#xff…...

Python练习(握手问题,进制转换,日期问题,位运算,求和)

一. 握手问题 代码实现 ans0for i in range(1,51):for j in range(i1,51):if i<7 and j<7:continueelse:ans 1print(ans) 这道题可以看成是50个人都握了手减去7个人没握手的次数 答案&#xff1a;1204 二.将十进制整数拆解 2.1门牌制作 代码实现 ans0for i in ra…...

小程序分类页面

1创建cate分支 2.cate滑动界面布局 获取滑动界面高度 3.获取并渲染一级分类的列表数据 4.渲染二级和三级分类列表 获取二级列表的数据 5.渲染二级分类列表的UI结构 6.动态渲染三级分类列表...

HTML + CSS 题目

1.说说你对盒子模型的理解? 一、是什么 对一个文档进行布局的时候&#xff0c;浏览器渲染引擎会根据标准之一的css基础盒模型&#xff0c;将所有元素表示为一个个矩形的盒子。 一个盒子由四个部分组成: content&#xff0c;padding&#xff0c;border&#xff0c;margin 下…...

计算机视觉|ViT详解:打破视觉与语言界限

一、ViT 的诞生背景 在计算机视觉领域的发展中&#xff0c;卷积神经网络&#xff08;CNN&#xff09;一直占据重要地位。自 2012 年 AlexNet 在 ImageNet 大赛中取得优异成绩后&#xff0c;CNN 在图像分类任务中显示出强大能力。随后&#xff0c;VGG、ResNet 等深度网络架构不…...

Node JS 调用模型Xenova_all-MiniLM-L6-v2实战

本篇通过将句子数组转换为句子的向量表示&#xff0c;并通过平均池化和归一化处理&#xff0c;生成适合机器学习或深度学习任务使用的特征向量为例&#xff0c;演示通过NodeJS 的方式调用Xenova/all-MiniLM-L6-v2 的过程。 关于 all-MiniLM-L6-v2 的介绍&#xff0c;可以参照上…...

React + TypeScript 实战指南:用类型守护你的组件

TypeScript 为 React 开发带来了强大的类型安全保障&#xff0c;这里解析常见的一些TS写法&#xff1a; 一、组件基础类型 1. 函数组件定义 // 显式声明 Props 类型并标注返回值 interface WelcomeProps {name: string;age?: number; // 可选属性 }const Welcome: React.FC…...

ASP.NET Core JWT认证与授权

1.JWT结构 JSON Web Token&#xff08;JWT&#xff09;是一种用于在网络应用之间安全传输声明的开放标准&#xff08;RFC 7519&#xff09;。它通常由三部分组成&#xff0c;以紧凑的字符串形式表示&#xff0c;在身份验证、信息交换等场景中广泛应用。 2.JWT权限认证 2.1添…...

【车规芯片】如何引导时钟树生长方向

12nm车规DFTAPR项目中&#xff0c;我们可以看到&#xff0c;绝大部分的sink都受控于xxxx_tessent_occ_clk_cpu_inst/tessent_persistent_cell_clock_out_mux/C10_ctmi_1这个mux&#xff0c;这是我们DFT设计结果&#xff1a; 这里我们重新打开place的数据 Anchor&#xff0c;也就…...

突破传统:用Polars解锁ICU医疗数据分析新范式

一、ICU数据革命的临界点 在重症监护室&#xff08;ICU&#xff09;&#xff0c;每秒都在产生关乎生死的关键数据&#xff1a;从持续监测的生命体征到高频更新的实验室指标&#xff0c;从呼吸机参数到血管活性药物剂量&#xff0c;现代ICU每天产生的数据量级已突破TB级别。传统…...

《深度学习实战》第11集:AI大模型压缩与加速

深度学习实战 | 第11集&#xff1a;AI大模型压缩与加速 在深度学习领域&#xff0c;随着模型规模的不断增大&#xff0c;模型的推理速度和部署效率成为实际应用中的关键挑战。本篇博客将带你深入了解模型压缩与加速的核心技术&#xff0c;并通过一个实战项目展示如何使用知识蒸…...

golang进阶知识专项-理解值传递

在 Go 语言中&#xff0c;所有函数的参数传递都是值传递&#xff08;Pass by Value&#xff09;。当你将一个变量作为参数传递给函数时&#xff0c;实际上传递的是该变量的副本&#xff0c;而不是变量本身。理解这一点对于避免常见的编程错误至关重要。根据不同的类型&#xff…...

OCPP与ISO 15118集成:实现即插即充与车网互动(V2G)- 慧知开源充电桩平台

OCPP与ISO 15118集成&#xff1a;实现即插即充与车网互动&#xff08;V2G&#xff09; 引言 随着电动汽车&#xff08;EV&#xff09;与电网双向能量交互&#xff08;V2G&#xff09;技术的成熟&#xff0c;OCPP协议与ISO 15118标准的协同成为智能充电基础设施的核心挑战。本文…...

大语言模型中温度参数(Temperature)的核心原理

大语言模型中温度参数&#xff08;Temperature&#xff09;的核心原理是通过调整模型输出的概率分布&#xff0c;控制生成结果的随机性和多样性。以下是其原理的详细说明&#xff1a; 一、定义与核心作用 温度参数是生成式模型&#xff08;如GPT系列&#xff09;中的一个超参数…...

K8s控制器Deployment详解

回顾 ReplicaSet 控制器,该控制器是用来维护集群中运行的 Pod 数量的&#xff0c;但是往往在实际操作的时候&#xff0c;我们反而不会去直接使用 RS&#xff0c;而是会使用更上层的控制器&#xff0c;比如说 Deployment。 Deployment 一个非常重要的功能就是实现了 Pod 的滚动…...

鸿蒙HarmonyOS评论功能小demo

评论页面小demo 效果展示 1.拆解组件&#xff0c;分层搭建 我们将整个评论页面拆解为三个组件&#xff0c;分别是头部导航&#xff0c;评论项&#xff0c;回复三个部分&#xff0c;然后统一在index界面导入 2.头部导航界面搭建 Preview Component struct HmNavBar {// 属性&a…...

基于PyTorch的深度学习3——基于autograd的反向传播

反向传播&#xff0c;可以理解为函数关系的反向传播。...

日期格式与字符串不匹配bug

异常特征&#xff1a;java.lang.IllegalArgumentException: invalid comparison: java.time.LocalDateTime and java.lang.String ### Error updating database. Cause: java.lang.IllegalArgumentException: invalid comparison: java.time.LocalDateTime and java.lang.Str…...

打印三角形及Debug

打印三角形及Debug package struct; ​ public class TestDemo01 {public static void main(String[] args) {//打印三角形 五行 ​for (int i 1; i < 5; i) {for (int j 5 ; j >i; j--) {System.out.print(" ");}for (int k1;k<i;k) {System.out.print(&…...