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

Sqldelight无法创建数据库表,测试提示无LocalMember表

SqlDelight测试报错:no such table: LocalMember

使用SqlDelight实现本地数据持久化时,运行测试出现以下错误:

org.sqlite.SQLiteException: [SQLITE_ERROR] SQL error or missing database (no such table: LocalMember)

此前功能运行正常,新建一个无其他依赖的测试项目后仍出现相同错误。相关代码及配置如下:

测试代码

class LocalDataTest {
    private lateinit var db: database
    private lateinit var localData: LocalData

    @BeforeEach
    fun setUp() {
        val driver: SqlDriver = JdbcSqliteDriver(JdbcSqliteDriver.IN_MEMORY) //实际项目用文件DB+Koin注入,同样报错
        database.Schema.create(driver)
        db = database(driver)
        localData = LocalData(db)
    }

    @Test
    fun addMember() {
        runBlocking {
            localData.addMember(LocalMember("1", "test"))
            val member = db.dataQueries.selectAll().executeAsOne()
            assertEquals("test", member.name)
        }
    }
}

SqlDelight SQL文件

CREATE TABLE IF NOT EXISTS LocalMember (
    id TEXT PRIMARY KEY,
    name TEXT NOT NULL
);


selectAll:
SELECT * FROM LocalMember;

upsert:
-- Insert or ignore the record
INSERT OR IGNORE INTO LocalMember (id, name)
VALUES (?, ?);

-- Then update the record assuming it exists
UPDATE LocalMember
SET
    name = COALESCE(?, name)
WHERE id = ?;

settings.gradle.kts

pluginManagement {
    repositories {
        gradlePluginPortal()
        maven("https://maven.pkg.jetbrains.space/public/p/compose/dev")
        mavenCentral()
    }

    plugins {
        kotlin("jvm").version(extra["kotlin.version"] as String)
        kotlin("plugin.serialization").version(extra["kotlin.version"] as String)
        id("org.jetbrains.compose").version(extra["compose.version"] as String)
        id("app.cash.sqldelight").version("2.0.0") apply false
    }
}

build.gradle.kts

dependencies {
 implementation("app.cash.sqldelight:sqlite-driver:2.0.0")
}

sqldelight {
    databases {
        create("database") {
            packageName.set("com.ayitinya.data")
            generateAsync.set(true)
        }
    }
}

解决方法
  • 检查SQL文件存放路径
    SqlDelight要求SQL文件必须放在src/main/sqldelight/[packageName]或src/test/sqldelight/[packageName]目录下,对应你设置的packageName.set("com.ayitinya.data"),路径应该是src/main/sqldelight/com/ayitinya/data(测试场景用src/test下的对应路径)。如果文件放错位置,Schema生成时不会包含该表,直接导致测试时找不到表。

  • 适配异步生成配置
    你在配置里开了generateAsync.set(true),这会生成协程异步API,但测试里直接调用的executeAsOne()是同步方法,容易出现线程或API不匹配问题。要么把generateAsync改成false,要么用异步版本的API:

    val member = db.dataQueries.selectAll().executeAsOneAsync().await()
    
  • 验证Schema生成结果
    去build/generated/sqldelight目录下查看自动生成的代码,确认database.Schema里包含LocalMember表的创建语句。如果没有,先执行./gradlew clean build --refresh-dependencies清理缓存并重新构建,再检查生成结果。

  • 确认测试数据库初始化成功
    对于内存数据库,可以在Schema创建后加验证代码,确保表确实被创建:

    val result = driver.executeQuery(null, "SELECT name FROM sqlite_master WHERE type='table' AND name='LocalMember';", 0)
    assert(result.next()) { "LocalMember表未创建成功" }
    
  • 排查SQL语法兼容性
    虽然你的SQL看起来没问题,但SqlDelight对语法细节要求严格,比如语句分隔、注释格式。可以先简化SQL文件,只保留CREATE TABLE语句测试,确认表能正常创建后,再逐步添加查询和upsert语句。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 00:38:15