Spring Boot与Flyway实现自动化数据库版本控制
一、为什么使用Flyway
最简单的一个项目是一个软件连接到一个数据库,但是大多数项目中我们不仅要处理我们开发环境的副本,还需要处理其他很多副本。例如:开发环境、测试环境、生产环境。想到数据库管理,我们立刻就能想到一系列问题
- 如何快速收集执行脚本的清单
- 执行的脚本总要人工执行,是否可以通过机器执行
- 执行的脚本是否已经在数据库执行过
- 执行的脚本是否全部在数据库中执行过
- 执行的脚本如何回退
- 如何初始化一个空数据库实例
Flyway是一款数据库版本控制管理工具,它可以简单的、可靠的升级你的数据库。它能帮助解决上面的问题。Flyway核心是记录所有版本演化和状态的MetaData,首次启动创建默认名为SCHEMA_VERSION的元素表。表中保存了版本,描述,要执行的sql脚本等信息。
Flyway已经支持数据库包括:Oracle, SQL Server, SQL Azure, DB2, DB2 z/OS, MySQL
(including Amazon RDS), MariaDB, Google Cloud SQL, PostgreSQL
(including Amazon RDS and Heroku), Redshift, Vertica, H2, Hsql, Derby,
SQLite, SAP HANA, solidDB, Sybase ASE and Phoeni
官网链接:https://flywaydb.org/
二、SpringBoot集成Flyway
2.1 简单示例
参考版本信息
示例信息 | 版本 |
---|---|
springboot | 2.7.5 |
flyway | 7.15.0 |
mysql | 8.0.28 |
2.1.1.创建SpringBoot应用,并添加flyway-core依赖,本例中将实现初始化脚本到mysql数据库,因此同时引入了驱动依赖 mysql-connector-java
<dependency><groupId>org.flywaydb</groupId><artifactId>flyway-core</artifactId><version>7.15.0</version>
</dependency>
参考pom.xml依赖如下
<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.28</version></dependency><dependency><groupId>org.flywaydb</groupId><artifactId>flyway-core</artifactId><version>7.15.0</version></dependency><dependency><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter-api</artifactId><version>5.8.2</version><scope>test</scope></dependency></dependencies>
2.1.2.在application.properties中设置flyway信息
server.port=7002##是否启动,默认开启
spring.flyway.enabled = true
## 当迁移发现数据库非空且存在没有元数据的表时,自动执行基准迁移,新建schema_version表
spring.flyway.baseline-on-migrate=true
# 与 baseline-on-migrate: true 搭配使用
spring.baseline-version: 0
##脚本存放路径
spring.flyway.locations = classpath:db/migration
##当flyway第一次运行时,会在我们对应的数据库中新建一个记录脚本运行情况的
spring.flyway.table=sat_version
## 编码格式,默认UTF-8
spring.flyway.encoding=UTF-8
2.1.3.脚本整理
将脚本整理到resource/db.migration路径下,例如
参考SQL脚本信息如下
create table if not exists test_plan_project
(test_plan_id varchar(50) null,project_id varchar(50) null,constraint test_plan_project_pkunique (test_plan_id, project_id)
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE utf8mb4_general_ci;insert into test_plan_project(test_plan_id, project_id) select id test_plan_id, project_id project_id from test_plan;
- 版本化迁移 :执行一遍,版本号唯一,有重复会报错:格式:V+版本号 +双下划线+描述+结束符
- 重复的迁移 :不需要版本号,脚本发生变化启动就会执行:格式:R+双下划线+描述+结束符
- 撤消迁移 :格式:U+版本号 +双下划线+描述+结束符
2.1.4.运行启动主类,运行日志如下,从日志中可以看到如下信息
- 启动后正确链接到数据库
- 验证迁移脚本成功
- 使用命令行的方式创建了一张名称为sat_version 的记录表,这里要注意,所有脚本一旦执行了就会在sat_version中创建记录,如果出错引发问题,可以删除表中记录,反正启动的时候还会再执行,当然生产环境不建议此方法,但生产环境上部署的包都是验证过无问题的包也不会出现此问题
- 执行了resource/db.migration 目录下的脚本,并执行成功
2.2 常见问题
2.2.1.Caused by: org.flywaydb.core.api.FlywayException: Found non-empty schema(s)
Caused by: org.flywaydb.core.api.FlywayException: Found non-empty schema(s) `runoob` but no schema history table. Use baseline() or set baselineOnMigrate to true to initialize the schema history table.at org.flywaydb.core.Flyway$1.execute(Flyway.java:200) ~[flyway-core-7.15.0.jar:na]at org.flywaydb.core.Flyway$1.execute(Flyway.java:170) ~[flyway-core-7.15.0.jar:na]at org.flywaydb.core.Flyway.execute(Flyway.java:586) ~[flyway-core-7.15.0.jar:na]
问题原因:第一执行的时候没有找到schema history table ,这张表其实就是application.properties文件中spring.flyway.table属性配置的表,因此要么使用命令创建一个或者在application.properties文件中设置 spring.flyway.baseline-on-migrate=true,
2.2.2.Caused by: org.flywaydb.core.api.FlywayException: Unsupported Database: MySQL 5.7
Caused by: org.flywaydb.core.api.FlywayException: Unsupported Database: MySQL 5.7at org.flywaydb.core.internal.database.DatabaseTypeRegister.getDatabaseTypeForConnection(DatabaseTypeRegister.java:106) ~[flyway-core-8.4.2.jar:na]at org.flywaydb.core.internal.jdbc.JdbcConnectionFactory.<init>(JdbcConnectionFactory.java:75) ~[flyway-core-8.4.2.jar:na]at org.flywaydb.core.FlywayExecutor.execute(FlywayExecutor.java:143) ~[flyway-core-8.4.2.jar:na]at org.flywaydb.core.Flyway.migrate(Flyway.java:124) ~[flyway-core-8.4.2.jar:na]
问题原因:flyway-core对数据库版本有要求,例如flyway-core的当前最高版本V8.4.3,不能使用 MySQL 5.7, 当flyway-core 降低到V7.15.0后 问题解决,所以匹配flyway-core和数据库版本后问题即可解决
三、总结
- 使用Flyway之前部署脚本方式一般为开发人员按照顺序汇总数据库的升级脚, 然后DBA或者售后在生产库中按照顺序执行升级脚本。
- 使用Flyway之后部署脚本方式就变更为开发人员将脚本构建到程序包中, 部署程序包后启动时Flyway自动执行脚本升级。
相关文章:
Spring Boot与Flyway实现自动化数据库版本控制
一、为什么使用Flyway 最简单的一个项目是一个软件连接到一个数据库,但是大多数项目中我们不仅要处理我们开发环境的副本,还需要处理其他很多副本。例如:开发环境、测试环境、生产环境。想到数据库管理,我们立刻就能想到一系列问…...
input角度:I2C触摸屏驱动分析和编写一个简单的I2C驱动程序
往期内容 本专栏往期内容: input子系统的框架和重要数据结构详解-CSDN博客input device和input handler的注册以及匹配过程解析-CSDN博客input device和input handler的注册以及匹配过程解析-CSDN博客编写一个简单的Iinput_dev框架-CSDN博客GPIO按键驱动分析与使用&…...
SQL-lab靶场less1-4
说明:部分内容来源于网络,如有侵权联系删除 前情提要:搭建sql-lab本地靶场的时候发现一些致命的报错: 这个程序只能在php 5.x上运行,在php 7及更高版本上,函数“mysql_query”和一些相关函数被删除…...
【生成模型之二】diffusion model模型
【算法简历修改、职业规划、校招实习咨询请私信联系】 【Latent-Diffusion 代码】 生成模型分类概述 Diffusion Model,这一深度生成模型,源自物理学中的扩散现象,呈现出令人瞩目的创新性。与传统的生成模型,如VAE、GAN相比&…...
记录 Maven 版本覆盖 Bug 的解决过程
背景 在使用 Maven 进行项目管理时,依赖版本的管理是一个常见且重要的环节。最近,在我的项目中遇到了一个关于依赖版本覆盖的 Bug,这个问题导致了 Apollo 框架的版本不一致,影响了项目的正常运行。以下是我解决这个问题的过程记录…...
【K8S系列】Kubernetes Service 基础知识 详细介绍
在 Kubernetes 中,Service 是一种抽象的资源,用于定义一组 Pod 的访问策略。它为这些 Pod 提供了一个稳定的访问入口,解决了 Pod 可能频繁变化的问题。本文将详细介绍 Kubernetes Service 的类型、功能、使用场景、DNS 和负载均衡等方面。 1.…...
python在物联网领域的数据应用分析与实战!
引言 物联网(IoT)是一个快速发展的领域,涉及到各种设备和传感器的连接与数据交换。随着设备数量的激增,数据的产生速度也在不断加快。 如何有效地分析和利用这些数据,成为了物联网应用成功的关键。Python作为一种强大的编程语言,因其简洁易用的特性和丰富的库支持,成为…...
目标跟踪算法-卡尔曼滤波详解
卡尔曼滤波是一种递归的优化算法,用于估计一个系统的动态状态,常用于跟踪、导航、时间序列分析等领域。它的关键在于使用一系列测量数据(通常含噪声)来估计系统的真实状态,使得估计值更接近实际情况。卡尔曼滤波器适合…...
SpringBoot后端开发常用工具详细介绍——application多环境配置与切换
文章目录 引言介绍application.yml(主配置文件)application-dev.yml(开发环境配置)application-test.yml(测试环境配置)application-prod.yml(生产环境配置)激活配置文件参考内容 引…...
php反序列化漏洞典型例题
1.靶场环境 ctfhub-技能树-pklovecloud 引用题目: 2021-第五空间智能安全大赛-Web-pklovecloud 2.过程 2.1源代码 启动靶场环境,访问靶场环境,显示源码:直接贴在下面: <?php include flag.php; class pks…...
浅析Android View绘制过程中的Surface
前言 在《浅析Android中View的测量布局流程》中我们对VSYNC信号到达App进程之后开启的View布局过程进行了分析,经过对整个App界面的View树进行遍历完成了测量和布局,确定了View的大小以及在屏幕中所处的位置。但是,如果想让用户在屏幕上看到…...
基于卷积神经网络的大豆种子缺陷识别系统,resnet50,mobilenet模型【pytorch框架+python源码】
更多目标检测和图像分类识别项目可看我主页其他文章 功能演示: 大豆种子缺陷识别系统,卷积神经网络,resnet50,mobilenet【pytorch框架,python源码】_哔哩哔哩_bilibili (一)简介 基于卷积神…...
HarmonyOS项目开发一多简介
目录 一、布局能力概述 二、自适应布局 三、响应式布局 四、典型布局场景 一、布局能力概述 布局决定页面元素排布及显示:在页面设计及开发中,布局能力至关重要,主要通过组件结构来确定使用何种布局。 自适应布局与响应式布局࿱…...
C++基础三
构造函数 构造函数(初始化类成员变量): 1、属于类的成员函数之一 2、构造函数没有返回类型 3、构造函数的函数名必须与类名相同 4、构造函数不允许手动调用(不能通过类对象调用) 5、构造函数在类对象创建时会被自动调用 6、如果没有显示声…...
利用ChatGPT完成2024年MathorCup大数据挑战赛-赛道A初赛:台风预测与分析
利用ChatGPT完成2024年MathorCup大数据挑战赛-赛道A初赛:台风预测与分析 引言 在2024年MathorCup大数据挑战赛中,赛道A聚焦于气象数据分析,特别是台风的生成、路径预测、和降水风速特性等内容。本次比赛的任务主要是建立一个分类评价模型&…...
Linux系统操作篇 one -文件指令及文件知识铺垫
Linux操作系统入门-系统篇 前言 Linux操作系统与Windows和MacOS这些系统不同,Linux是黑屏的操作系统,操作方式使用的是指令和代码行来进行,因此相对于Windows和MacOS这些带有图形化界面的系统,Linux的入门门槛和上手程度要更高&…...
隨筆20241028 ISR 的收缩与扩展及其机制解析
在 Kafka 中,ISR(In-Sync Replicas) 是一组副本,它们与 Leader 保持同步,确保数据一致性。然而,ISR 的大小会因多种因素而变化,包括收缩和扩展。以下是 ISR 收缩与扩展的详细解释及其背后的机制…...
linux-字符串相关命令
1、cut 提取文件每一行中的内容 下面是一些常用的 cut 命令选项的说明: -c, --characters列表:提取指定字符位置的数据。-d, --delimiter分界符:指定字段的分隔符,默认为制表符。-f, --fieldsLIST:提取指定字段的数据…...
ES6 函数的扩展
ES6 之前,不能直接为函数的参数指定默认值,只能采用变通的方法 ES6 允许为函数的参数设置默认值,即直接写在参数定义的后面 参数变量是默认声明的,所以不能用 let 或 const 再次声明 使用参数默认值时,函数不能有同名参…...
Mac 查看占用特定端口、终止占用端口的进程
在 macOS 上,可以使用以下命令来查看占用特定端口(例如 8080)的进程: lsof -i :8080命令说明 lsof:列出打开的文件和网络连接信息。-i :8080:筛选出正在监听 8080 端口的进程。 输出结果结构 执行上述命…...
C#入坑JAVA MyBatis入门 CURD 批量 联表分页查询
本文,分享 MyBatis 各种常用操作,不限于链表查询、分页查询等等。 1. 分页查询 在 下文的 的「3.4 selectPage」小节,我们使用 MyBatis Plus 实现了分页查询。除了这种方式,我们也可以使用 XML 实现分页查询。 这里,…...
RabbitMQ 安装(Windows版本)和使用
安装 安装包获取 可以自己找资源,我这里也有百度云的资源,如果没失效的话可以直接用。 通过百度网盘分享的文件:RabbitMQ 链接:https://pan.baidu.com/s/1rzcdeTIYQ4BqzHLDSwCgyw?pwdfj79 提取码:fj79 安装教程…...
Apache paimon表管理
表管理 2.9.4.1 管理快照 1)快照过期 Paimon Writer每次提交都会生成一个或两个快照。每个快照可能会添加一些新的数据文件或将一些旧的数据文件标记为已删除。然而,标记的数据文件并没有真正被删除,因为Paimon还支持时间旅行到更早的快照。它们仅在快照过期时被删除。 …...
java 第19天
一.Lambda表达式 前提是:参数是函数式接口才可以书写Lambda表达式 函数式接口条件: 1.接口 2.只有一个抽象方法 lambda表达式又称为匿名函数,允许匿名函数以参数的形式传入方法,简化代码 lambda表达式分为两部分()->{} …...
什么是服务器?服务器与客户端的关系?本地方访问不了网址与服务器访问不了是什么意思?有何区别
服务器是一种高性能的计算机,它通过网络为其他计算机(称为客户端)提供服务。这些服务可以包括文件存储、打印服务、数据库服务或运行应用程序等。服务器通常具有强大的处理器、大量的内存和大容量的存储空间,以便能够处理多个客户…...
Spring(1)—Spring 框架:Java 开发者的春天
一、关于Spring 1.1 简介 Spring 框架是一个功能强大的开源框架,主要用于简化 Java 企业级应用的开发,由被称为“Spring 之父”的 Rod Johnson 于 2002 年提出并创立,并由Pivotal团队维护。它提供了全面的基础设施支持,使开发者…...
MT1401-MT1410 码题集 (c 语言详解)
目录 MT1401归并排序 MT1402堆排序 MT1403后3位排序 MT1404小大大小排序 MT1405小大大小排序II MT1406数字重排 MT1407插入 MT1408插入 MT1409旋转数组 MT1410逆时针旋转数组 MT1401归并排序 c 语言实现代码 #include <stdio.h>// merge two subarrays void merge(int a…...
React基础语法
1.React介绍 React由Meta公司开发,是一个用于构建Web和原生交互界面的库 1.1 React优势 相较于传统基于DOM开发的优势 1.组件化的开发方式 2.不错的性能 相较于其他前端框架的优势 1.丰富的生态 2.跨平台支持 1.2React的时长情况 全球最流行,大厂…...
《Kadane‘s Algorithm专题:最大和连续子数组》
🚀 博主介绍:大家好,我是无休居士!一枚任职于一线Top3互联网大厂的Java开发工程师! 🚀 🌟 在这里,你将找到通往Java技术大门的钥匙。作为一个爱敲代码技术人,我不仅热衷…...
Vue基础(5)
ref属性 在 Vue2 中,ref是一个特殊的属性,用于在模板中获取对某个 DOM 元素或子组件的引用。通过 ref,我们可以在 JavaScript 代码中直接访问该 DOM 元素或组件实例。 示例: <template><div><input ref"inputField&quo…...
沈阳网站建设优秀公司/单页关键词优化费用
一般情况下,Linux系统管理员通过SSH服务来管理操作系统,但Docker的很多镜像不带SSH服务的。 基于commit命令创建 准备工作 首先,使用ubuntu镜像来创建一个容器: $ sudo docker run -it ubuntu /bin/bash root3c6ed6207883:/# 这…...
门户网站开发用什么框架好/参考网是合法网站吗?
摘要:机器人技术是当今世界备受关注的前沿课题,伴随着近年来人工智能技术不断的发展,机器人技术也成为了一个令人浮想联翩的技术领域。本文以大家喜闻乐见的中国传统的非完备信息二人军棋计算机博弈作为研究对象,军棋博弈的每方拥有25个棋子、12种类型棋子,每个棋子…...
wordpress模板加密/网络推广优化网站
安装xlwt:到python官网下载xlwt模块后,执行python setup.py install,或者在PyCharm的Project Interpreter输入xlwt后点击Install Package就可以了。操作xlwt:导入xlwt模块:import xlwt ;创建workbook:xlwt.Workbook()&…...
手机网站建设设计/百度推广中心
I值便利, 什么是I值便利, 我们可以把I当成一个整型的首字母, 在这里有两种方法可以实现. 涉及到的方法: objectAtIndex: 这里指的是打印数组里的第几个元素. 第一种方法是直接打印数组里有多少个元素. 第二种是直接把数组里的所有元素逐个打印出来. #import <Foundation/Fou…...
公司建网站会计分录/优秀营销软文范例100字
linux删除用户的方法:首先进入系统创建一个用户;然后对该用户一些信息目录查看;最后正确删除用户,代码为【[rootlocalhost /]# userdel -r haha】。本教程操作环境:linux5.9.8,DELL G3电脑。linux删除用户的…...
政府网站的域名/营销型网站建站
匿名对象 匿名对象是指创建对象时,只有创建对象的语句,却没有把对象地址值赋值给某个变量。 创建一个普通对象 Person p new Person(); 创建一个匿名对象 new Person(); 匿名对象的特点 l 创建匿名对象直接使用,没有变量名。 new Person().…...