我有一个相对较大的数据库,可能需要1到2分钟来初始化,是否可以在使用sqldelight(Kotlin多平台)时加载预填充的数据库,而不是在应用程序启动时初始化数据库?
ie3xauqp1#
对不起,我还不能添加任何评论,这将是更合适的。虽然没有直接回答你的问题,但1到2分钟对sqlite来说真的很长。你在干什麽?我首先要确保你正确地使用了交易。1-2分钟的插入数据将(可能)导致一个巨大的db文件。或者,我的问题,由于我不得不使用一个预填充的数据库是与大尺寸的.sq文件(超过30 MB的文本插入每个表),和SqlDeLight默默地中断生成,没有显示错误消息。在初始化sqldelight之前,你需要将db文件放在android上的assets和iOS上的bundle中,并将它们复制到各自的文件夹中。从android和ios的资源中加载数据库感觉工作量很大,这意味着共享项目不是唯一初始化数据的地方。Kotlin多平台库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) } }
字符串fullDb是库生成的类的FileResource,它与位于commonMain模块的resources/MR/files目录中的文件名相关联。其属性rawResId表示平台端资源ID。
6ss1mwsb2#
是的,但这很棘手。不仅仅是“多平台”。在尝试初始化sqldelight之前,您需要将db复制到db文件夹。这可能意味着当应用程序启动时,主线程上的i/o。现在没有标准的方法来做到这一点。在初始化sqldelight之前,你需要将db文件放在android上的assets和iOS上的bundle中,并将它们复制到各自的文件夹中。显然,您需要首先检查数据库是否存在,或者通过某种方式知道这是您第一次运行应用程序。如果您计划发布包含较新数据库的更新,则需要管理版本,而不仅仅是检查数据库的存在。虽然没有直接回答你的问题,但1到2分钟对sqlite来说真的很长。你在干什麽?我首先要确保你正确地使用了交易。1-2分钟的插入数据将(可能)导致一个巨大的db文件。
ma8fv8wu3#
您唯一需要做的就是使用驱动程序指定DB文件的路径。假设您的数据库位于/mnt/my_best_app_dbs/super.db中。现在,在Driver的name属性中传递路径。大概是这样的:
/mnt/my_best_app_dbs/super.db
name
val sqlDriver: SqlDriver = AndroidSqliteDriver(Schema, context, "/mnt/my_best_app_dbs/best.db")
字符串请记住,您可能需要具有允许您读取给定存储类型的权限。
icnyk63a4#
我已经将@Denis Luttcev的代码转换为ios目标端,它在我的Kotlin多平台项目中完美地工作。有一些麻烦弄清楚如何使它的工作,所以在情况下,其他人将需要它这里是我得到的:
actual class DriverFactory { actual fun createDriver(schema: SqlDriver.Schema, fileName: String): SqlDriver { val fileManager = NSFileManager.defaultManager val documentsPath = NSSearchPathForDirectoriesInDomains( directory = NSApplicationSupportDirectory, domainMask = NSUserDomainMask, expandTilde = true ).first() as NSString val dbDirectoryPath = documentsPath.stringByAppendingPathComponent("databases") val targetDbPath = documentsPath.stringByAppendingPathComponent("databases/$fileName") val sourceDbPath = MR.files.dbfile.path val directoryExists = fileManager.fileExistsAtPath(dbDirectoryPath) val databaseExists = fileManager.fileExistsAtPath(targetDbPath) if (databaseExists.not()) { memScoped { // you can use it to log errors val error: ObjCObjectVar<NSError?> = alloc() if (directoryExists.not()) { val createSuccess = fileManager.createDirectoryAtPath( path = dbDirectoryPath, withIntermediateDirectories = true, attributes = null, error = error.ptr ) } val copySuccess = fileManager.copyItemAtPath( srcPath = sourceDbPath, toPath = targetDbPath, error = error.ptr ) } } return NativeSqliteDriver(schema, fileName) } }
字符串
4条答案
按热度按时间ie3xauqp1#
对不起,我还不能添加任何评论,这将是更合适的。
虽然没有直接回答你的问题,但1到2分钟对sqlite来说真的很长。你在干什麽?我首先要确保你正确地使用了交易。1-2分钟的插入数据将(可能)导致一个巨大的db文件。
或者,我的问题,由于我不得不使用一个预填充的数据库是与大尺寸的.sq文件(超过30 MB的文本插入每个表),和SqlDeLight默默地中断生成,没有显示错误消息。
在初始化sqldelight之前,你需要将db文件放在android上的assets和iOS上的bundle中,并将它们复制到各自的文件夹中。
从android和ios的资源中加载数据库感觉工作量很大,这意味着共享项目不是唯一初始化数据的地方。
Kotlin多平台库Moko-resources解决了共享模块中数据库的单一源的问题。KMM的工作方式与Android和iOS相同。
不幸的是,使用这个功能几乎没有在库的样本中提出。我在预期的DatabaseDriverFactory类中添加了第二个方法(getDriver)以打开准备好的数据库,并在平台上实现了它。例如,对于androidMain:
字符串
fullDb是库生成的类的FileResource,它与位于commonMain模块的resources/MR/files目录中的文件名相关联。其属性rawResId表示平台端资源ID。
6ss1mwsb2#
是的,但这很棘手。不仅仅是“多平台”。在尝试初始化sqldelight之前,您需要将db复制到db文件夹。这可能意味着当应用程序启动时,主线程上的i/o。
现在没有标准的方法来做到这一点。在初始化sqldelight之前,你需要将db文件放在android上的assets和iOS上的bundle中,并将它们复制到各自的文件夹中。显然,您需要首先检查数据库是否存在,或者通过某种方式知道这是您第一次运行应用程序。
如果您计划发布包含较新数据库的更新,则需要管理版本,而不仅仅是检查数据库的存在。
虽然没有直接回答你的问题,但1到2分钟对sqlite来说真的很长。你在干什麽?我首先要确保你正确地使用了交易。1-2分钟的插入数据将(可能)导致一个巨大的db文件。
ma8fv8wu3#
您唯一需要做的就是使用驱动程序指定DB文件的路径。
假设您的数据库位于
/mnt/my_best_app_dbs/super.db
中。现在,在Driver的name
属性中传递路径。大概是这样的:字符串
请记住,您可能需要具有允许您读取给定存储类型的权限。
icnyk63a4#
我已经将@Denis Luttcev的代码转换为ios目标端,它在我的Kotlin多平台项目中完美地工作。有一些麻烦弄清楚如何使它的工作,所以在情况下,其他人将需要它这里是我得到的:
字符串