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

Android 调用Room.createFromAsset(";initialData.db";)时,`.db`文件应采用什么格式? 脚本,android,android-room,Android,Android Room,我试图用一些条目预先填充房间数据库。关于api调用的文档很清晰(),我也读了一篇很好的博客(),但我不熟悉实际预打包数据库文件的语法/格式(developmentData.db,在下面的示例中)。我在搜索过的任何地方都找不到任何文档 Room .databaseBuilder( context.applicationContext, MyDatabase::class.java, "my_database") .fallbackToDestruct

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

Room
  .databaseBuilder(
      context.applicationContext, 
      MyDatabase::class.java, 
      "my_database")
  .fallbackToDestructiveMigration()
  .createFromAsset("database/developmentData.db")
  .build()
思想 我遵循了导出模式的步骤。以下是该过程的结果,供参考。在本例中,我只是创建一个虚拟对象,以便在这里提问

{
  "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\")"
    ]
  }
}
以下是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.");
这里是错误。它没有加密,所以这一定是语法问题。
E/SQLiteLog:(26)文件已加密或不是数据库

问题:
调用
createFromAsset()
时引用的
.db
文件应采用什么格式?如果有现成的文档,我很乐意提供参考。

不太可能的服务器端数据库系统(MySQL、Oracle、SQL server等),关闭时,SQLite数据库是一个文件
createFromAsset()
需要的是那种文件,而不是SQL脚本

所以,我通常做的是:

  • 让应用程序使用Room的模式,使用标准Room stuff,在设备上创建一个空数据库
  • 从设备上复制该数据库(例如,在Android Studio中使用设备文件资源管理器)
  • 使用SQL浏览器或sqlite3或其他工具将数据添加到我的应用程序的表中

这样,我可以保证数据库将具有正确的结构和文件室元数据。

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

在应用程序中导出文件室数据库的架构。 这一步有很好的文档。简而言之,我需要将此注释添加到我的RoomDatabase类中。注意
exportSchema=true
部分。这会导致Gradle构建在
app/schemas
目录中删除.json文件

@Database(entities = [Library::class], version = 1, exportSchema = true)
abstract class MyDatabase : RoomDatabase() {
该json文件包含我在下一步中使用的
tableName
createSql
key:value对。看起来是这样的:

"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)",
创建SQLite二进制文件 然后,我使用一个名为的免费应用程序来实际创建所需的.db二进制文件,并参考上面提到的.json。一旦我在其中添加了一些记录并保存,数据就会毫无问题地预填充

将二进制文件放在正确的目录中 最后一个注意事项,我没有从文档中立即发现:调用
createFromAsset()
默认情况下在
/assets
目录中。此目录需要位于所需的源集中。例如,我将.db二进制文件放在这里:

/app/src/main/assets/initialData.db

它应该是一个SQLite数据库,我认为它可能需要由Room自己准备。“但它没有通过验证”--你能提供详细信息吗?很好的细节要求,谢谢。刚刚在问题中添加了这一点。该错误表明文件室试图打开的数据库文件本身已损坏。“这是我的developmentData.db的当前内容”——你的意思是说,
developmentData.db
是一个包含该文本的文本文件吗?如果是这样,请尝试SQLite数据库,而不是SQL脚本。例如,在创建数据库(sans
createFromAsset()
)之后,从设备上复制数据库。啊。。。我完全走错了方向。我想到了类似data.sql的东西,Spring可以执行它来预填充数据库。你说得对,这就解决了问题。下面我将尝试给出一个更完整的答案,但是@commonware应该得到认可。这个答案更简洁,从设备上复制db而不是检查json的想法比我在自己的答案中解释的更简单。我建议其他人遵循这个模式。出于好奇。。。您是将
room\u master\u table
添加到您的数据库中,还是只添加了您自己的表?如果没有JSON中的
setupQueries
中的表及其内容,我不会尝试这样做,但是如果我们不必担心
createFromAsset()
路径的问题,那会更方便。@humbleDev是的,如果您提到了JSON文件,您应该在回答中包含另一个有用的部分creationI的带有room_master_table代码的“setupquerys”实际上没有将json文件的该部分添加到我创建并传递到createFromAsset()的SQLite数据库中调用。尽管调用仍然成功,并按预期加载了数据。@Commonware-对此处的延迟评论表示歉意,但我试图使用设备中的数据库创建一些初始数据,但在我这样做时发现其中没有空间主表。您在拔出设备的数据库中找到了吗?@humbleDev:如果数据库是由文件室创建的,则为“是”。