1

我有一个相对较大的数据库,可能需要 1 到 2 分钟来初始化,是否可以在使用 sqldelight(kotlin 多平台)而不是在应用程序启动时初始化数据库时加载预填充的数据库?

4

3 回答 3

1

对不起,但我还不能添加任何评论,这会更合适......


虽然没有直接回答你的问题,但 1 到 2 分钟对于 sqlite 来说真的非常非常长。你在做什么?我首先要确保您正确使用交易。1-2 分钟的插入数据(可能)会导致一个巨大的 db 文件。

或者,我不得不使用预填充数据库的问题与 .sq 文件的大尺寸(每个表超过 30 MB 的 INSERT 文本)有关,并且 SqlDeLight 默默地中断了生成,没有显示错误消息。


在初始化 sqldelight 之前,您需要将 db 文件放在 android 上的 assets 和 iOS 上的 bundle 中,并将它们复制到各自的文件夹中。

必须从 android 和 ios 上的资源中加载 db 感觉需要做很多工作 + 这意味着共享项目不会是唯一初始化数据的地方。

Kotlin MultiPlatform 库Moko-resources解决了共享模块中数据库的单一来源问题。它适用于 KMM 的方式与适用于 Android 和 iOS 的方式相同。

不幸的是,图书馆的样本中几乎没有使用此功能。我在预期的类 DatabaseDriverFactory 中添加了第二个方法(getDriver)来打开准备好的数据库,并在平台上实现它。例如,对于 androidMain:

actual class DatabaseDriverFactory(private val context: Context) {
    actual fun createDriver(schema: SqlDriver.Schema, fileName: String): SqlDriver {
        return AndroidSqliteDriver(schema, context, fileName)
    }

    actual fun getDriver(schema: SqlDriver.Schema, fileName: String): SqlDriver {
        val database: File = context.getDatabasePath(fileName)

        if (!database.exists()) {
            val inputStream = context.resources.openRawResource(MR.files.dbfile.rawResId)
            val outputStream = FileOutputStream(database.absolutePath)

            inputStream.use { input: InputStream ->
                outputStream.use { output: FileOutputStream ->
                    input.copyTo(output)
                }
            }
        }

        return AndroidSqliteDriver(schema, context, fileName)
    }
}

MR.files.fullDb 是库生成的类中的 FileResource,它与位于 commonMain 模块的 resources/MR/files 目录中的文件名相关联。它的属性 rawResId 表示平台端资源 ID。

于 2021-05-19T12:04:26.473 回答
1

是的,但这可能很棘手。不仅仅是“多平台”。在尝试初始化 sqldelight 之前,您需要将 db 复制到 db 文件夹。这可能意味着应用程序启动时主线程上的 i/o。

现在没有标准的方法可以做到这一点。在初始化 sqldelight 之前,您需要将 db 文件放在 android 上的 assets 和 iOS 上的 bundle 中,并将它们复制到各自的文件夹中。显然,您首先要检查数据库是否存在,或者通过某种方式知道这是您的第一个应用程序运行。

如果您计划发布具有较新数据库的更新,则需要管理版本,而不仅仅是检查数据库是否存在。

虽然没有直接回答你的问题,但 1 到 2 分钟对于 sqlite 来说真的非常非常长。你在做什么?我首先要确保您正确使用交易。1-2 分钟的插入数据(可能)会导致一个巨大的 db 文件。

于 2019-08-05T17:07:40.820 回答
0

您唯一需要的是使用驱动程序指定 DB 文件的路径。

假设您的数据库位于/mnt/my_best_app_dbs/super.db. name现在,在 Driver的属性中传递路径。像这样的东西:

val sqlDriver: SqlDriver = AndroidSqliteDriver(Schema, context, "/mnt/my_best_app_dbs/best.db")

请记住,您可能需要具有允许您读取给定存储类型的权限。

于 2021-09-08T10:47:29.853 回答