如何生成适合我的房间方案的数据库?

How can I generate a DB, that fits my room scheme?

我有一个包含很多实体的数据库,我想在第一次创建数据库时从文件中预加载数据。为此,Room 的方案需要适合数据库文件的方案。由于手动将 json 方案转换为 SQLite 语句非常容易出错(我需要复制粘贴每一个语句并交换变量名)我正在寻找一种可能性来自动从该方案生成一个数据库,然后我只需要填充数据。 然而,显然在互联网上没有关于这是否可能的信息,甚至没有关于如何这样做的信息。这是我第一次使用 SQLite(通常我使用 MySQL),也是我第一次在 json 中看到数据库方案。 (因为标准的 MariaDB 导出选项总是只导出 CREATE TABLE 语句。) 有办法吗?或者 Room 是否提供了实际获取 create table 语句作为适当文本的方法,而不是拆分成大量 JSON 数组? 我按照 Android 开发人员指南上的指南获得了 json 方案,所以我已经有了那个文件。对于那些不知道它的结构的人,它看起来像这样:

{
  "formatVersion": 1,
  "database": {
    "version": 1,
    "identityHash": "someAwesomeHash",
    "entities": [
      {
        "tableName": "Articles",
        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `germanArticle` TEXT NOT NULL, `frenchArticle` TEXT, PRIMARY KEY(`id`))",
        "fields": [
          {
            "fieldPath": "id",
            "columnName": "id",
            "affinity": "INTEGER",
            "notNull": true
          },
          {
            "fieldPath": "germanArticle",
            "columnName": "germanArticle",
            "affinity": "TEXT",
            "notNull": true
          },
          {
            "fieldPath": "frenchArticle",
            "columnName": "frenchArticle",
            "affinity": "TEXT",
            "notNull": false
          }
        ],
        "primaryKey": {
          "columnNames": [
            "id"
          ],
          "autoGenerate": false
        },
        "indices": [
          {
            "name": "index_Articles_germanArticle",
            "unique": true,
            "columnNames": [
              "germanArticle"
            ],
            "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_Articles_germanArticle` ON `${TABLE_NAME}` (`germanArticle`)"
          },
          {
            "name": "index_Articles_frenchArticle",
            "unique": true,
            "columnNames": [
              "frenchArticle"
            ],
            "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_Articles_frenchArticle` ON `${TABLE_NAME}` (`frenchArticle`)"
          }
        ],
        "foreignKeys": []
      },
...

注意:我的问题不是,如何从方案中创建 Room DB。要接收方案,我已经必须创建所有实体和数据库。但是如何让 Room 创建为 SQL 的结构来预填充我的数据库。但是,我认为答案是一个很好的解释,事实上我在生成的 Java 文件中找到了我正在搜索的 SQL-Statements,这是一个很棒的提示。 ;)

Is there a way? Or does Room provide anyway to actually get the create table statements as a proper text, not split up in tons of JSON arrays?

您不能简单地为 Room 提供 CREATE SQL,您需要做的是从 JSON 生成 java/Kotlin classes(实体)和然后将这些 classes 添加到项目中。

  • 原生 SQLite(即不使用 Room)将是另一回事,因为它可以在运行时完成。

Room 的工作方式是,数据库是从 class 注释的 @Entity 中生成的(在编译时)。

Entity/classes 必须存在,编译才能正确生成它生成的代码。

此外,实体必须 incorporated/included 变成数据库的 class,用 @Database 注释(这个 class 通常是抽象的) .

此外,要访问数据库 tables,您有 SQL 的抽象 classes 或接口,每个都用 @Dao 注释,并且再次需要实体 classes 因为 SQL 在编译时被检查。

例如您提供的 JSON 等同于:-

@Entity(
        indices = {
                @Index(value = "germanArticle", name = "index_Articles_germanArticle", unique = true),
                @Index(value = "frenchArticle", name = "index_Articles_frenchArticle", unique = true)
        }
        , primaryKeys = {"id"}
)
public class Articles {
    //@PrimaryKey // Could use this as an alternative
    long id;
    @NonNull
    String germanArticle;
    String frenchArticle;
}
  • 因此您的流程必须转换 JSON 以创建上述内容,然后可以将其复制到项目中。

然后您需要一个 Class 数据库,例如:-

@Database(entities = {Articles.class},version = 1)
abstract class MyDatabase extends RoomDatabase {
}
  • 请注意,Dao classes 将按照 :-

    添加到上面的正文中
      abstract MyDaoClass getDao();
    

Or does Room provide anyway to actually get the create table statements as a proper text, not split up in tons of JSON arrays?

是的 ....

在这个阶段,如果你编译它会生成 java(上面的 MyDatabase_Impl 即数据库的名称 class 后缀为 _Impl)。但是因为没有道classes/interfaces。从 Room 的角度来看,数据库将不可用(因此甚至不会创建)。

生成的部分代码将是:-

  @Override
  public void createAllTables(SupportSQLiteDatabase _db) {
    _db.execSQL("CREATE TABLE IF NOT EXISTS `Articles` (`id` INTEGER NOT NULL, `germanArticle` TEXT NOT NULL, `frenchArticle` TEXT, PRIMARY KEY(`id`))");
    _db.execSQL("CREATE UNIQUE INDEX IF NOT EXISTS `index_Articles_germanArticle` ON `Articles` (`germanArticle`)");
    _db.execSQL("CREATE UNIQUE INDEX IF NOT EXISTS `index_Articles_frenchArticle` ON `Articles` (`frenchArticle`)");
    _db.execSQL("CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)");
    _db.execSQL("INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'f7294cddfc3c1bc56a99e772f0c5b9bb')");
  }
  • 如您所见,文章 table 和两个索引已创建,room_master_table 用于验证检查。