Android 调用Room.createFromAsset(";initialData.db";)时,`.db`文件应采用什么格式? 脚本
我试图用一些条目预先填充房间数据库。关于api调用的文档很清晰(),我也读了一篇很好的博客(),但我不熟悉实际预打包数据库文件的语法/格式(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
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\")"
]
}
}
以下是mydevelopmentData.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脚本。例如,在创建数据库(sanscreateFromAsset()
)之后,从设备上复制数据库。啊。。。我完全走错了方向。我想到了类似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:如果数据库是由文件室创建的,则为“是”。