创建后如何将数据导入到Room数据库中? [英] How to import data into a Room database upon creation?

查看:180
本文介绍了创建后如何将数据导入到Room数据库中?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经升级了我的应用程序,使其具有Room数据库.当用户升级到新的应用程序版本时,我需要将数据导入存储在其他数据结构中的Room数据库中.乍看之下,Room似乎已经支持这种情况:

I've upgraded my app to feature a Room database. When the user upgrades to my new app version, I need to import data into the Room Database that was stored in other data structures. At first glance it looks like Room already supports this scenario:

    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导入数据时,遇到了一个异常:

However, when trying to actually import data, things get more complicated. When I try to import data using Entities, Daos and the AppDatabase, I run into an Exception:

java.lang.IllegalStateException:getDatabase递归调用

java.lang.IllegalStateException: getDatabase called recursively

似乎不可能使用所有不错的Room Entities,Daos等将数据导入数据库.但是, onCreate 方法确实提供对基础SQLite数据库的访问.也许我打算将数据导入那里?

It doesn't seem to be possible to import data into the database using all the nice Room Entities, Daos and so forth. The onCreate method does however provide access to the underlying SQLite database. Maybe I'm meant to import data there?

直接使用SQLite数据库的文档非常薄.它以红色大警告开头,不要直接访问SQLite数据库,而要使用Room抽象!

The documentation on using the SQLite database directly is rather thin. And it starts with a big red warning not to access the SQLite database directly but to use the Room abstractions instead!

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

How should I proceed? How is this usually done?

我现在用实体定义的表已经存在了吗?还是在开始导入数据之前需要使用SQL语句创建表?

Do the tables I've defined with Entities already exist at this point? Or do I need to create the tables with SQL statements before I can start to import my data?

推荐答案

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

There are basically two ways to import data into a Room database upon creation. The first uses an ugly workaround but then allows you to use Room Entities and all. The second is to work directly with the SQLiteDatabase instance provided.

1.插入一个警卫并处理房间摘要

    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);
    }

无论是否调用了 onCreate 回调, doImport 布尔值都是协议的防护.不过,它必须是一个数组,因为无法在 onCreate 中将新值分配给简单的布尔值.

The doImport boolean serves as a guard to protocol, whether the onCreate callback has been called. It needs to be an array though, because a new value couldn't be assigned to a simple boolean from within onCreate.

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

Notice also the seemingly senseless line db.userDao().get(17);. It is necessary to access the database in order for the onCreate callback to be called. Otherwise doImport would remain false at this point, regardless of whether or not the database was newly created.

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

Finally in the last if block the database may be accessed with all the nice abstractions Room provides.

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();

比我怀疑的痛苦要少得多.尽管您需要使用字符串来识别数据库表和字段,这很容易出错!

A lot less painful then I suspected. You need to work with strings though to identify database tables and fields, which is error prone!

这篇关于创建后如何将数据导入到Room数据库中?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆