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

Spring Boot Kotlin集成FF4J遇BadSqlGrammarException,无法建表

Spring Boot Kotlin集成FF4J时数据库表无法自动创建问题排查

问题描述

在Spring Boot Kotlin项目中集成FF4J时,数据库架构未自动创建,调试显示数据源配置正常,但抛出BadSqlGrammarException。配置类及依赖如下:

配置类代码

@Configuration
@ConditionalOnClass(FF4j::class)
class FF4JConfiguration {

    @field:Value("\${spring.ff4j.datasource.url}")
    private lateinit var driverUrl: String

    @field:Value("\${spring.datasource.driver-class-name}")
    private lateinit var driverClass: String

    @field:Value("\${spring.datasource.username}")
    private lateinit var user: String

    @field:Value("\${spring.datasource.password}")
    private lateinit var password: String

    @Bean
    fun getFF4j(): FF4j {
        val source = MysqlDataSource()
        source.setURL(driverUrl)
        source.password = password
        source.user = user
        val fF4j = FF4j()
        fF4j.featureStore = FeatureStoreSpringJdbc().apply { setDataSource(source) }
        fF4j.propertiesStore = PropertyStoreSpringJdbc().apply { setDataSource(source) }
        fF4j.eventRepository = JdbcEventRepository(source)
        fF4j.audit(true)
        fF4j.autoCreate(true)
        return fF4j
    }
}

依赖配置(build.gradle.kts)

implementation("org.ff4j:ff4j-core:1.8.12")
implementation("org.ff4j:ff4j-web:1.8.12")
implementation("org.ff4j:ff4j-store-springjdbc:1.8.12")
implementation("mysql:mysql-connector-java:8.0.30")

原因分析

  1. FF4J版本与MySQL 8.0兼容性问题:FF4J 1.8.12是较旧版本,其Spring JDBC存储的建表SQL未适配MySQL 8.0的语法规范(比如使用了MySQL 8.0弃用的关键字、字符集配置),导致执行建表语句时触发BadSqlGrammarException。
  2. 数据源未显式指定驱动类:配置中注入了driverClass但未设置到MysqlDataSource中,虽然MySQL 8.0驱动可自动加载,但显式配置能避免潜在的版本适配问题。
  3. autoCreate的作用误解:ff4j.autoCreate(true)仅负责特性/属性的自动创建,并不触发数据库表结构的初始化,FF4J的Spring JDBC存储不会主动执行建表脚本,需手动触发。

解决方案

1. 升级FF4J到兼容MySQL 8.0的版本

将FF4J依赖升级到2.x系列的最新稳定版,该版本已修复对MySQL 8.0的适配问题:

implementation("org.ff4j:ff4j-core:2.0.12")
implementation("org.ff4j:ff4j-web:2.0.12")
implementation("org.ff4j:ff4j-store-springjdbc:2.0.12")

2. 显式配置数据源驱动类

在创建MysqlDataSource时添加驱动类设置:

val source = MysqlDataSource().apply {
    setURL(driverUrl)
    password = password
    user = user
    driverClassName = driverClass // 新增此行
}

3. 手动触发表结构初始化

在配置存储时调用createSchema()方法,强制执行建表脚本:

@Bean
fun getFF4j(): FF4j {
    val source = MysqlDataSource().apply {
        setURL(driverUrl)
        password = password
        user = user
        driverClassName = driverClass
    }

    // 初始化特性存储表
    val featureStore = FeatureStoreSpringJdbc().apply {
        setDataSource(source)
        createSchema()
    }
    // 初始化属性存储表
    val propertyStore = PropertyStoreSpringJdbc().apply {
        setDataSource(source)
        createSchema()
    }
    // 初始化事件存储表
    val eventRepo = JdbcEventRepository(source).apply {
        createSchema()
    }

    return FF4j().apply {
        featureStore = featureStore
        propertiesStore = propertyStore
        eventRepository = eventRepo
        audit(true)
        autoCreate(true)
    }
}

4. 使用FF4J Spring初始化器简化配置

通过FF4jSpringInitializer自动处理数据源配置与表初始化:

@Bean
fun getFF4j(): FF4j {
    val source = MysqlDataSource().apply {
        setURL(driverUrl)
        password = password
        user = user
        driverClassName = driverClass
    }

    val initializer = FF4jSpringInitializer()
    initializer.setDataSource(source)
    initializer.createSchema() // 自动创建所有所需表
    initializer.audit = true
    initializer.autoCreate = true

    return initializer.ff4j
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 14:20:22