简体   繁体   English

是否可以使用 sqldelight 从本地资源加载预先填充的数据库

[英]Is it possible to load a pre-populated database from local resource using sqldelight

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

Yes, but it can be tricky.是的,但这可能很棘手。 Not just for "Multiplatform".不仅适用于“多平台”。 You need to copy the db to the db folder before trying to init sqldelight.在尝试初始化 sqldelight 之前,您需要将 db 复制到 db 文件夹。 That probably means i/o on the main thread when the app starts.这可能意味着应用程序启动时主线程上的 i/o。

There is no standard way to do this now.现在没有标准的方法来做到这一点。 You'll need to put the db file in assets on android and in a bundle on iOS and copy them to their respective folders before initializing sqldelight.在初始化 sqldelight 之前,您需要将 db 文件放在 android 上的资产和 iOS 上的捆绑包中,并将它们复制到各自的文件夹中。 Obviously you'll want to check if the db exists first, or have some way of knowing this is your first app run.显然,您首先要检查数据库是否存在,或者有某种方式知道这是您第一次运行应用程序。

If you're planning on shipping updates that will have newer databases, you'll need to manage versions outside of just a check for the existance of the db.如果您计划发布具有更新数据库的更新,则需要管理版本,而不仅仅是检查数据库是否存在。

Although not directly answering your question, 1 to 2 minutes is really, really long for sqlite.虽然没有直接回答你的问题,但 1 到 2 分钟对于 sqlite 来说真的很长。 What are you doing?你在干嘛? I would first make sure you're using transactions properly.我首先要确保您正确使用交易。 1-2 minutes of inserting data would (probably) result in a huge db file. 1-2 分钟的插入数据会(可能)导致一个巨大的 db 文件。

Sorry, but I can't add any comments yet, which would be more appropriate...对不起,但我还不能添加任何评论,这会更合适...


Although not directly answering your question, 1 to 2 minutes is really, really long for sqlite.虽然没有直接回答你的问题,但 1 到 2 分钟对于 sqlite 来说真的很长。 What are you doing?你在干嘛? I would first make sure you're using transactions properly.我首先要确保您正确使用交易。 1-2 minutes of inserting data would (probably) result in a huge db file. 1-2 分钟的插入数据会(可能)导致一个巨大的 db 文件。

Alternatively, my problem due to which I had to use a pre-populated database was associated with the large size of .sq files (more than 30 MB text of INSERTs per table), and SqlDeLight silently interrupted the generation, without displaying error messages.或者,我必须使用预填充数据库的问题与大尺寸 .sq 文件(每个表的 INSERT 文本超过 30 MB)相关联,SqlDeLight 静默中断生成,不显示错误消息。


You'll need to put the db file in assets on android and in a bundle on iOS and copy them to their respective folders before initializing sqldelight.在初始化 sqldelight 之前,您需要将 db 文件放在 android 上的资产和 iOS 上的捆绑包中,并将它们复制到各自的文件夹中。

Having to load a db from resources on both android and ios feels a lot of work + it means the shared project wont be the only place where the data is initialised.必须从 android 和 ios 上的资源加载数据库感觉很多工作+这意味着共享项目不会是唯一初始化数据的地方。

Kotlin MultiPlatform library Moko-resources solves the issue of a single source for a database in a shared module. Kotlin MultiPlatform 库Moko-resources解决了共享模块中数据库单一源的问题。 It works for KMM the same way for Android and iOS.它适用于 KMM 的方式与适用于 Android 和 iOS 的方式相同。

Unfortunately, using this feature are almost not presented in the samples of library.不幸的是,使用此功能几乎没有出现在库的示例中。 I added a second method (getDriver) to the expected class DatabaseDriverFactory to open the prepared database, and implemented it on the platform.我在期望的类DatabaseDriverFactory中添加了第二个方法(getDriver)来打开准备好的数据库,并在平台上实现。 For example, for androidMain:例如,对于 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 is the FileResource from the class generated by the library, it is associated with the name of the file located in the resources/MR/files directory of the commonMain module. MR.files.fullDb 是库生成的类中的 FileResource,它与位于 commonMain 模块的 resources/MR/files 目录中的文件名相关联。 It property rawResId represents the platform-side resource ID.它的属性 rawResId 表示平台端资源 ID。

The only thing you need is to specify the path to the DB file using the driver.您唯一需要的是使用驱动程序指定 DB 文件的路径。

Let's assume your DB lies in /mnt/my_best_app_dbs/super.db .假设您的数据库位于/mnt/my_best_app_dbs/super.db Now, pass the path in the name property of the Driver.现在,在驱动程序的name属性中传递路径。 Something like this:像这样的东西:

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

Keep in mind that you might need to have permissions that allow you to read a given storage type.请记住,您可能需要具有读取给定存储类型的权限。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何在 Android Studio 中使用 Kotlin 访问本地预填充的 sqlite 数据库? - How to access a local, pre-populated sqlite database using Kotlin in Android Studio? 如何添加到先前预填充的 Room 数据库? - How to add to previously pre-populated Room database? 在 Android 应用程序中安装预填充的 SQLite 数据库的最佳方法是什么? - What is the best way to install a pre-populated SQLite database in an Android application? 无法从 sqldelight v1.4.1 访问生成的数据库类 - Cannot access generated Database Class from sqldelight v1.4.1 从本地目录加载资源而没有类 - Load resource from local directory with no class 在 Android 上使用 SQLDelight JVM 驱动程序 - Using SQLDelight JVM Driver on Android 如何在 Sqldelight 中使用复合主键从表中删除行列表? - How to delete a list of rows from a table using composite primary keys in Sqldelight? 我可以使用 SqlDelight 创建一个内存数据库以在 Android 中运行吗? - Can I create an in-memory database with SqlDelight for running in Android? SqlDelight、MySql 和 Flow:未在数据库更改时调用 Flow 的收集 lambda - SqlDelight, MySql, and Flow: Flow's collect lambda not invoked on database changes 如何使用 Glide 从本地存储加载图像 - How to load image from local storage using Glide
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM