调用 Room.createFromAsset("initialData.db") 时,`.db` 文件应采用什么格式?

bmo*_*ody 3 android android-room

设想

我正在尝试用一些条目预先填充房间数据库。关于api调用的文档很清楚(developer.android docs),并且我读过一篇很好的博客(Medium文章),但我不熟悉实际预打包数据库文件的语法/格式(developmentData.db在下面的示例中) 。我在搜索过的任何地方都找不到任何文档。

Room
  .databaseBuilder(
      context.applicationContext, 
      MyDatabase::class.java, 
      "my_database")
  .fallbackToDestructiveMigration()
  .createFromAsset("database/developmentData.db")
  .build()
Run Code Online (Sandbox Code Playgroud)

想法

我已按照文档导出架构。以下是该过程的结果,供参考。在这种情况下,我只是创建一个虚拟对象,以便在这里提出我的问题。

{
  "formatVersion": 1,
  "database": {
    "version": 1,
    "identityHash": "0ad43a6714902eedbb90c1f77ab1ffcb",
    "entities": [
      {
        "tableName": "library_table",
        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`libraryId` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `title` TEXT NOT NULL, `description` TEXT NOT NULL)",
        "fields": [
          {
            "fieldPath": "libraryId",
            "columnName": "libraryId",
            "affinity": "INTEGER",
            "notNull": true
          },
          {
            "fieldPath": "title",
            "columnName": "title",
            "affinity": "TEXT",
            "notNull": true
          },
          {
            "fieldPath": "description",
            "columnName": "description",
            "affinity": "TEXT",
            "notNull": true
          }
        ],
        "primaryKey": {
          "columnNames": [
            "libraryId"
          ],
          "autoGenerate": true
        },
        "indices": [],
        "foreignKeys": []
      }
    ],
    "setupQueries": [
      "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
      "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, \"0ad43a6714902eedbb90c1f77ab1ffcb\")"
    ]
  }
}
Run Code Online (Sandbox Code Playgroud)

以下是 my 的当前内容developmentData.db,但验证失败:

CREATE TABLE IF NOT EXISTS `library_table` (
`libraryId` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
`title` TEXT NOT NULL,
`description` TEXT NOT NULL
);
INSERT INTO `library_table` (title, description) VALUES ("Library 1", "A whopping amazing library!");
INSERT INTO `library_table` (title, description) VALUES ("Library the Second", "A smashing library indeed!");
INSERT INTO `library_table` (title, description) VALUES ("Thou Third Library", "Quite possibly the most amazing library ever.");
INSERT INTO `library_table` (title, description) VALUES ("Ye Olde Fouthe Librarye", "So many profound thoughts in here.");
Run Code Online (Sandbox Code Playgroud)

这是错误。它没有加密,所以这一定是语法问题。 E/SQLiteLog: (26) file is encrypted or is not a database

问题

.db调用中引用的文件应采用什么格式createFromAsset()?如果某处有现有文档,我将很高兴提供参考。

bmo*_*ody 5

这里的解决方案是创建一个实际的 SQLite 数据库二进制文件,而不是上面的一系列 SQL 语句,并使用该文件。创建它的过程并没有从文档中立即明显看出,所以我将在这里解释它,以防其他人需要指出正确的方向。@CommonsWare 应该因这个答案而受到赞扬,因为他为我指明了正确的方向。

导出应用程序中 Room 数据库的架构。

这里有关于此步骤的很好的文档。简而言之,我需要将此注释添加到我的 RoomDatabase 类中。记下该exportSchema = true部分。这会导致 Gradle 构建在目录中删除 .json 文件app/schemas

@Database(entities = [Library::class], version = 1, exportSchema = true)
abstract class MyDatabase : RoomDatabase() {
Run Code Online (Sandbox Code Playgroud)

该 json 文件包含tableNamecreateSql在下一步中使用的键:值对。它看起来像这样:

"tableName": "library_table",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`libraryId` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `title` TEXT NOT NULL, `description` TEXT NOT NULL)",
Run Code Online (Sandbox Code Playgroud)

创建 SQLite 二进制文件

然后,我使用一个名为DB Browser for SQLite的免费应用程序来实际创建我需要的 .db 二进制文件,并参考上面提到的 .json。一旦我向其中添加了一些记录并保存,数据就会预先填充,没有任何问题。

将二进制文件放在正确的目录中

最后一点,我没有从文档中立即明显地发现:createFromAsset()默认情况下,对looks的调用在/assets目录中。该目录需要位于所需的源集内。例如,我将 .db 二进制文件放置在这里:
<project-root>/app/src/main/assets/initialData.db