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

Kotlin Multiplatform项目中配置SQLDelight多独立数据库的正确方法咨询

Kotlin Multiplatform项目中配置SQLDelight多独立数据库的正确方法咨询

我最近在开发一个面向Desktop(JVM)和Android的Kotlin Multiplatform应用,想要通过SQLDelight配置两个完全独立的SQLite数据库:

  • CardDatabase:存储核心应用数据(比如卡片收藏集)
  • SettingsDatabase:存储简单的用户设置(比如语言偏好)

我的核心需求是让这两个数据库的Schema、自动生成的查询类和数据模型完全隔离,以此保持代码架构的整洁性,但在配置Gradle的SQLDelight插件时,接连遇到了两个棘手的问题,折腾了好几天都没解决,特意来请教大家正确的配置方式。

我遇到的两类核心问题

问题1:重复声明(Redeclaration)错误

当我给每个数据库指定独立的包名后,构建时会抛出大量Redeclaration相关的编译错误。从错误日志来看,SQLDelight似乎把两个数据库的.sq文件都编译到了每个数据库的生成代码目录中——比如SettingsDatabase的生成代码里居然出现了CardDatabase的CardDatabaseQueries和CardEntity类,导致重复定义。

错误日志示例:

e: .../build/generated/sqldelight/code/SettingsDatabase/commonMain/com/example/myapp/db/CardDatabaseQueries.kt:14:14
Redeclaration: class CardDatabaseQueries : TransacterImpl
e: .../build/generated/sqldelight/code/SettingsDatabase/commonMain/com/example/myapp/db/CardEntity.kt:7:19
Redeclaration: data class CardEntity : Any
...(所有来自CardDatabase的实体和查询类都会报重复声明)

问题2:“SqlDelight files must be placed in a package directory”错误

当我尝试用srcDirs属性显式指定每个数据库对应的.sq文件目录时,哪怕我的文件已经放在完全符合包结构的路径下,构建还是会抛出这个路径错误。

我已经尝试过的解决方案

为了隔离两个数据库,我做了以下尝试,但都没成功:

  • 将两个数据库的.sq文件分别放到独立的子目录中
  • 在sqldelight配置块里给每个数据库分配了唯一的packageName
  • 用srcDirs属性明确告知每个数据库去哪里读取自己的.sq文件(按照Gradle的配置逻辑,这应该是正确的做法,但就是不生效)

我的当前配置细节

依赖版本(libs.versions.toml)

kotlin = "2.0.0"
composeMultiplatform = "1.6.11"
sqldelight = "2.0.2"
agp = "8.2.2"

项目目录结构

我的.sq文件已经严格按数据库分开存放,目录结构如下:

composeApp/
└── src/
    └── commonMain/
        └── sqldelight/
            └── com/
                └── example/
                    └── myapp/
                        └── db/
                            ├── cards/
                            │   └── CardDatabase.sq
                            └── settings/
                                └── SettingsDatabase.sq

尝试的SQLDelight Gradle配置(build.gradle.kts)

这是我最后一次尝试的配置,希望通过srcDirs明确隔离两个数据库的源文件:

sqldelight {
    databases {
        create("CardDatabase") {
            packageName.set("com.example.myapp.db.cards")
            srcDirs.set(listOf("src/commonMain/sqldelight/com/example/myapp/db/cards"))
        }
        create("SettingsDatabase") {
            packageName.set("com.example.myapp.db.settings")
            srcDirs.set(listOf("src/commonMain/sqldelight/com/example/myapp/db/settings"))
        }
    }
}

示例SQL文件内容

CardDatabase.sq(核心数据Schema):

CREATE TABLE SetEntity (
    setId TEXT NOT NULL PRIMARY KEY
    -- 其他业务字段省略...
);
CREATE TABLE PokemonCardEntity (
    id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
    setId TEXT NOT NULL,
    FOREIGN KEY(setId) REFERENCES SetEntity(setId)
    -- 其他业务字段省略...
);
selectAllSets: SELECT * FROM SetEntity;

SettingsDatabase.sq(设置数据Schema):

CREATE TABLE SettingsEntity (
    key TEXT NOT NULL PRIMARY KEY,
    value TEXT NOT NULL
);
getSetting: SELECT value FROM SettingsEntity WHERE key = :key;

我最想弄明白的问题

到底应该怎么正确配置SQLDelight插件,才能让这两个数据库完全独立工作?具体来说:

  1. 每个数据库只编译自己目录下的.sq文件
  2. 生成的代码完全隔离,不会出现重复声明
  3. 不会再出现路径相关的错误

是不是我使用srcDirs的方式有误?或者SQLDelight还有其他我没注意到的配置属性可以实现这种隔离?

感谢各位大佬的帮忙!


内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.08 14:24:34