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插件,才能让这两个数据库完全独立工作?具体来说:
- 每个数据库只编译自己目录下的
.sq文件 - 生成的代码完全隔离,不会出现重复声明
- 不会再出现路径相关的错误
是不是我使用srcDirs的方式有误?或者SQLDelight还有其他我没注意到的配置属性可以实现这种隔离?
感谢各位大佬的帮忙!
内容来源于stack exchange

