【问题标题】:How to import data into a Room database upon creation?如何在创建时将数据导入 Room 数据库?
【发布时间】:2020-08-06 18:54:42
【问题描述】:

我已将我的应用升级为具有 Room 数据库。当用户升级到我的新应用程序版本时,我需要将数据导入到存储在其他数据结构中的房间数据库中。乍一看,Room 似乎已经支持这种场景:

    db = Room.databaseBuilder(getApplicationContext(), AppDatabase.class, "my-db")
            .addCallback(new RoomDatabase.Callback() {

                @Override
                public void onCreate(@NonNull SupportSQLiteDatabase db) {
                    super.onCreate(db);

                    // IMPORT DATA
                }
            })
            .build();

但是,当尝试实际导入数据时,事情会变得更加复杂。当我尝试使用 Entities、Daos 和 AppDatabase 导入数据时,我遇到了一个异常:

java.lang.IllegalStateException: getDatabase 被递归调用

似乎不可能使用所有漂亮的 Room Entities、Daos 等将数据导入数据库。但是,onCreate 方法确实提供了对底层 SQLite 数据库的访问。也许我打算在那里导入数据?

直接使用 SQLite 数据库的documentation 比较薄。它以一个大红色警告开始,不要直接访问 SQLite 数据库,而是使用 Room 抽象!

我应该如何进行?这通常是怎么做的?

此时我使用实体定义的表是否已经存在?还是需要先用 SQL 语句创建表,然后才能开始导入数据?

【问题讨论】:

标签: android android-room


【解决方案1】:

基本上有两种方法可以在创建时将数据导入 Room 数据库。第一个使用丑陋的解决方法,但随后允许您使用房间实体和所有。第二种是直接使用提供的 SQLiteDatabase 实例。

1.插入警卫并使用 Room 抽象

    final boolean[] doImport = { false };

    db = Room.databaseBuilder(getApplicationContext(), AppDatabase.class, "my-db")
            .addCallback(new RoomDatabase.Callback() {
                @Override
                public void onCreate(@NonNull SupportSQLiteDatabase db) {
                    super.onCreate(db);
                    doImport[0] = true;
                }
            })
            .build();

    db.userDao().get(17);

    if (doImport[0]) {
        UserEntity user = new UserEntity();
        user.name = "John Doe";
        db.userDao().insert(user);
    }

doImport 布尔值用作协议的保护,无论是否调用了 onCreate 回调。但它必须是一个数组,因为无法从 onCreate 中将新值分配给简单的布尔值。

还要注意看似毫无意义的行db.userDao().get(17);。必须访问数据库才能调用 onCreate 回调。否则doImport 将在此时保持false,无论数据库是否是新创建的。

最后在最后一个if 块中,可以使用 Room 提供的所有不错的抽象来访问数据库。

2。直接使用 SQLiteDatabase

    db = Room.databaseBuilder(getApplicationContext(), AppDatabase.class, "my-db")
            .addCallback(new RoomDatabase.Callback() {
                @Override
                public void onCreate(@NonNull SupportSQLiteDatabase db) {
                    super.onCreate(db);

                    db.beginTransaction();
                    ContentValues values = new ContentValues();
                    values.put("name", "John Doe");
                    db.insert("UserEntity", SQLiteDatabase.CONFLICT_ABORT, values);
                    db.setTransactionSuccessful();
                    db.endTransaction();
                }
            })
            .build();

没有我想象的那么痛苦。您需要使用字符串来识别数据库表和字段,这很容易出错!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-12-09
    • 1970-01-01
    • 2020-01-13
    • 1970-01-01
    • 2023-01-21
    • 2020-05-14
    • 2020-08-13
    相关资源
    最近更新 更多