You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Kotlin SpringBoot下Liquibase与R2DBC+MySQL兼容问题咨询

Kotlin-SpringBoot-R2DBC-Liquibase环境下Liquibase失效问题解决

问题场景

搭建Kotlin-SpringBoot-R2DBC-Liquibase技术栈时,遇到以下问题:

  • JDBC配置模式下,数据库连接与Liquibase迁移均正常工作
  • 切换为R2DBC配置后,数据库连接正常,但Liquibase完全失效,未执行任何迁移操作

JDBC配置

build.gradle.kts

import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

plugins {
    id("org.springframework.boot") version "3.0.6"
    id("io.spring.dependency-management") version "1.1.0"
    id("org.graalvm.buildtools.native") version "0.9.20"
    id("org.jetbrains.kotlin.plugin.jpa") version "1.8.21"
    kotlin("jvm") version "1.7.22"
    kotlin("plugin.spring") version "1.7.22"
}

group = "com.abahafart.kotlin.template"
version = "0.0.1-SNAPSHOT"
java.sourceCompatibility = JavaVersion.VERSION_17

configurations {
    compileOnly {
        extendsFrom(configurations.annotationProcessor.get())
    }
}

repositories {
    mavenCentral()
}

dependencies {
    implementation("org.springframework.boot:spring-boot-starter-data-jdbc")
//  implementation("org.springframework.boot:spring-boot-starter-data-r2dbc")
    implementation("org.springframework.boot:spring-boot-starter-web")
    implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
    implementation("org.jetbrains.kotlin:kotlin-reflect")
    implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
    implementation("org.liquibase:liquibase-core")
    implementation("org.springframework.boot:spring-boot-starter-data-jpa")
    developmentOnly("org.springframework.boot:spring-boot-devtools")
    runtimeOnly("mysql:mysql-connector-java:8.0.32")
//  runtimeOnly("dev.miku:r2dbc-mysql:0.8.2.RELEASE")
    testImplementation("org.springframework.boot:spring-boot-starter-test")
}

tasks.withType<KotlinCompile> {
    kotlinOptions {
        freeCompilerArgs = listOf("-Xjsr305=strict")
        jvmTarget = "17"
    }
}

tasks.withType<Test> {
    useJUnitPlatform()
}

application.yml

spring:
  datasource:
    url: jdbc:mysql://localhost:3333/library?tlsVersion=TLSv1.2
    username: mysql
    password: mysqlpw
#  r2dbc:
#    url: r2dbc:mysql://localhost:3333/library?tlsVersion=TLSv1.2
#    username: mysql
#    password: mysqlpw
#    pool:
#      enabled: true
#      initial-size: 1
#      max-size: 20

R2DBC配置

build.gradle.kts

import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

plugins {
    id("org.springframework.boot") version "3.0.6"
    id("io.spring.dependency-management") version "1.1.0"
    id("org.graalvm.buildtools.native") version "0.9.20"
    id("org.jetbrains.kotlin.plugin.jpa") version "1.8.21"
    kotlin("jvm") version "1.7.22"
    kotlin("plugin.spring") version "1.7.22"
}

group = "com.abahafart.kotlin.template"
version = "0.0.1-SNAPSHOT"
java.sourceCompatibility = JavaVersion.VERSION_17

configurations {
    compileOnly {
        extendsFrom(configurations.annotationProcessor.get())
    }
}

repositories {
    mavenCentral()
}

dependencies {
//  implementation("org.springframework.boot:spring-boot-starter-data-jdbc")
    implementation("org.springframework.boot:spring-boot-starter-data-r2dbc")
    implementation("org.springframework.boot:spring-boot-starter-web")
    implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
    implementation("org.jetbrains.kotlin:kotlin-reflect")
    implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
    implementation("org.liquibase:liquibase-core")
    implementation("org.springframework.boot:spring-boot-starter-data-jpa")
    developmentOnly("org.springframework.boot:spring-boot-devtools")
    runtimeOnly("mysql:mysql-connector-java:8.0.32")
    runtimeOnly("dev.miku:r2dbc-mysql:0.8.2.RELEASE")
    testImplementation("org.springframework.boot:spring-boot-starter-test")
}

tasks.withType<KotlinCompile> {
    kotlinOptions {
        freeCompilerArgs = listOf("-Xjsr305=strict")
        jvmTarget = "17"
    }
}

tasks.withType<Test> {
    useJUnitPlatform()
}

application.yml

spring:
#  datasource:
#    url: jdbc:mysql://localhost:3333/library?tlsVersion=TLSv1.2
#    username: mysql
#    password: mysqlpw
  r2dbc:
    url: r2dbc:mysql://localhost:3333/library?tlsVersion=TLSv1.2
    username: mysql
    password: mysqlpw
    pool:
      enabled: true
      initial-size: 1
      max-size: 20

解决方法

1. 添加JDBC Starter依赖

在R2DBC模式的build.gradle.kts中,添加JDBC Starter依赖(无需注释R2DBC依赖):

implementation("org.springframework.boot:spring-boot-starter-data-jdbc")

2. 保留JDBC数据源配置

在R2DBC模式的application.yml中,取消spring.datasource相关配置的注释,让Liquibase通过JDBC连接执行迁移:

spring:
  datasource:
    url: jdbc:mysql://localhost:3333/library?tlsVersion=TLSv1.2
    username: mysql
    password: mysqlpw
  r2dbc:
    url: r2dbc:mysql://localhost:3333/library?tlsVersion=TLSv1.2
    username: mysql
    password: mysqlpw
    pool:
      enabled: true
      initial-size: 1
      max-size: 20

原因说明

  • Liquibase核心实现完全基于JDBC API,目前无原生支持R2DBC的反应式数据库连接。
  • JDBC环境下,Spring Boot自动配置会检测到DataSource实例,自动初始化Liquibase并绑定该数据源执行迁移。
  • 切换到R2DBC后,应用主数据源变为反应式的ConnectionFactory,Spring Boot的Liquibase自动配置无法找到可用的JDBC DataSource,因此不会触发迁移流程。
  • 保留JDBC依赖和配置后,Liquibase可通过JDBC连接正常执行迁移,应用业务逻辑仍使用R2DBC反应式连接,两者互不冲突。

内容的提问来源于stack exchange,提问作者5frags

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 05:14:52