编程开源技术交流,分享技术与知识

网站首页 > 开源技术 正文

教你使用Flyway管理SQL脚本的3种方法

wxchong 2024-06-19 22:26:56 开源技术 26 ℃ 0 评论

引言

Hello,大家好,这里是Anyin。

在我们日常的后端Java开发工作当中,不可避免的与SQL脚本打交道。每个公司对于SQL脚本的管理方式可能都不太相同,但是都会有一个共同的痛点:遗漏SQL脚本。

我们在日常的开发过程中,一般都是多人协作并且是多环境切换,例如:开发、测试、演示、生产等环境,基本开发流程是开发人员在开发环境开发功能完成之后,代码合并到测试环境并部署,测试人员测试完成之后代码合并到演示环境并部署,最后在演示环境验收完成之后,代码接着合并到生产环境并部署。

在这个过程中,可能会涉及大量的SQL脚本,并且在环境切换的时候出现遗漏,例如:在演示环境出现一个问题,那么开发可能写一个SQL脚本,然后在演示环境执行了,因为流程是往下走的,最后会造成演示环境和生产环境表结构正确,开发和测试缺异常。

基于以上问题,今天我们来看看怎么使用Flyway管理SQL脚本从而解决脚本遗漏的问题。

方法一:使用插件方式

Flyway提供了基于Maven的插件方式。配置如下:

<plugin>
    <groupId>org.flywaydb</groupId>
    <artifactId>flyway-maven-plugin</artifactId>
    <version>4.1.0</version>
    <configuration>
        <user>${db.user}</user>
        <password>${db.password}</password>
        <driver>com.mysql.jdbc.Driver</driver>
        <url>${jdbc.url}</url>
        <locations>
            <location>db/migration</location>
        </locations>
        <table>schema_version</table>
        <cleanDisabled>true</cleanDisabled>
        <outOfOrder>true</outOfOrder>
        <baselineOnMigrate>true</baselineOnMigrate>
    </configuration>
</plugin>

配置项目说明

? db.userdb.passwordjdbc.url 为数据库的配置,这里使用变量的形式,因为我们不同环境的数据库配置都不一样的

? db/migration 配置了脚本的存放目录

? schema_version 配置了管理脚本在数据库的表名称

因为不同环境具有不同的数据库配置,所以我们还在Maven配置了不同的profiles,这里我们配置一个demo环境:

<profile>
    <id>demo</id>
    <properties>
        <jdbc.url>jdbc:mysql://127.0.0.1:3306/anyin-demo?characterEncoding=UTF-8<![CDATA[&]]>useSSL=false<![CDATA[&]]>autoReconnect=true<![CDATA[&]]>allowMultiQueries=true</jdbc.url>
        <db.user>root</db.user>
        <db.password>rootroot</db.password>
    </properties>
    <activation>
        <activeByDefault>true</activeByDefault>
    </activation>
</profile>

接着,我们在resources/db/migration目录下新增我们的数据库脚本,如下图:

? 这里我们使用不同的文件夹区分不同的版本迭代,例如这里是v1.0.0和v1.0.1版本,注意这里是用下划线

? SQL脚本的名称规范:版本_时间__文件描述.sql,时间建议到分钟即可,这样子多人开发的时候避免出现一样的时间戳或者文件名,注意在文件描述之前是两个下划线

最后,我们就可以通过mvn命令执行SQL脚本了,指令如下:

# mvn clean package
# mvn flyway:repair flyway:migrate

执行之后的打印下如下:

数据库新增的信息如下:

? 在执行脚本之前一定需要先执行package指令,把对应的SQL脚本放到target/classes目录下,Flyway是从该目录获取脚本进行执行的

? flyway:repair 是修复指令,使用场景是对于已经执行过的SQL脚本,后来开发人员又手动修改,这样子会导致文件的checksum值不一样,从而阻断SQL脚本的执行。这时候需要开发人员人工确认SQL脚本没问题,然后在执行该指令,这样子会修改对应数据库的checksum值,保证SQL脚本和数据库的执行记录是一致的

? flyway:migrate 在确认了前置工作已经准备就绪,则可以执行该指令,从而执行SQL脚本到数据库中

对于一般的单体项目或者小型项目,使用插件的方式没什么大问题,而对于分布式的微服务项目则不太合适。一般的分布式微服务都会把配置放入配置中心,项目启动的时候直接从配置中心读取对应的配置,而插件的方式是需要把数据库的账号密码写入pom.xml文件中,这样显然不合适。

为了解决这个问题,我们接着看第二个方案。

方法二:使用编码方式

Flyway除了提供Maven Plugin的方式,还提供对应的API,使得我们可以通过代码执行SQL脚本。

首先,需要添加flyway-core的依赖,如下:

<dependency>
    <groupId>org.flywaydb</groupId>
    <artifactId>flyway-core</artifactId>
</dependency>

接着,新增一个FlywayMigrate类,代码如下:

@Component
@Slf4j
public class FlywayMigrate implements InitializingBean {


    @Value("${spring.datasource.druid.url}")
    private String url;


    @Value("${spring.datasource.druid.username}")
    private String username;


    @Value("${spring.datasource.druid.password}")
    private String password;


    @Value("${anyin.flyway.table}")
    private String table;


    @Value("${anyin.flyway.locations}")
    private String[] locations;


    @Override
    public void afterPropertiesSet() throws Exception {
        Flyway flyway = Flyway.configure()
                .locations(locations)
                .table(table)
                .cleanDisabled(true)
                .outOfOrder(true)
                .baselineOnMigrate(true)
                .dataSource(url, username, password)
                .load();
        flyway.repair();
        flyway.migrate();
    }
}

在微服务项目中,我们的配置都可以从配置中心获取,所以这里我们通过@Value注入对应的数据库配置,接着实现InitializingBean接口,在afterPropertiesSet方法实现我们的脚本执行逻辑。

该方式为编码方式,如果对于SQL脚本的执行有特殊需求的话(例如审核),则可以通过该方式进行定制化开发。如果没有特殊需求的话,那还是略显繁琐,其实spring-boot-autoconfigure组件已经为我们做了这种的事情

我们接着看第三个方案。

方法三:使用SpringBoot内置自动配置

在Spring Boot 中spring-boot-autoconfigure组件其实已经为我们做了关于Flyway自动化配置相关的事情了,我们只需要引入flyway-core的依赖即可,如下:

<dependency>
    <groupId>org.flywaydb</groupId>
    <artifactId>flyway-core</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-autoconfigure</artifactId>
</dependency>

这样子在启动服务的时候,会自动为我们执行SQL脚本。启动打印日志如下:

最后

至此,通过Flyway管理脚本的3种方式已经分享完,如果有什么问题欢迎交流。

相关代码地址:

? https://gitee.com/anyin/shiro-to-token

? https://gitee.com/anyin/anyin-cloud

注意,对于生产环境而言,建议还是不要让Flyway自动执行,还是需要人工审核,否则某个人来个delete 没有where条件,那就背锅了

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表