首页 > 解决方案 > 如何将数据添加到新创建的 Room 数据库?

问题描述

我尝试在 onCreate 方法中导入数据:

    db = Room.databaseBuilder(applicationContext,
            AppDatabase::class.java,
            "my-database")
        .allowMainThreadQueries()
        //.fallbackToDestructiveMigration()
        .addCallback(object: RoomDatabase.Callback() {
            override fun onCreate(db: SupportSQLiteDatabase) {
                Log.d("RoomDatabase.Callback", "onCreate called")
                importData()
            }
        })
        .build()

但这会导致

IllegalStateException:递归调用 getDatabase

在创建数据库后进行导入也不起作用:

    var performInitialImport = false

    db = Room.databaseBuilder(applicationContext,
            AppDatabase::class.java,
            "my-database")
        .allowMainThreadQueries()
        //.fallbackToDestructiveMigration()
        .addCallback(object: RoomDatabase.Callback() {
            override fun onCreate(db: SupportSQLiteDatabase) {
                Log.d("RoomDatabase.Callback", "onCreate called")
                performInitialImport = true
            }
        })
        .build()

    Log.d("PerformInitialImport", "$performInitialImport")

    if (performInitialImport) {
        importData()
    }

因为在数据库建立后控制流继续之前回调没有被执行。这从以下事实可以看出

D/PerformInitialImport:假

来之前

D/RoomDatabase.Callback: onCreate 调用

在应用程序的运行日志中。

我迷路了。我如何在首次创建时将数据导入数据库?

更新:importData方法使用AppDatabase在第一行创建的实例。db传递给的参数onCreate是底层的低级数据库。自然,我想使用 DAO 和我已经拥有的实体来填充数据库......

标签: androidandroid-room

解决方案


你得到这种行为的原因是构建没有打开数据库,直到你使用数据库才打开它,然后如果数据库不存在,它将被创建并调用 onCreate。

因此performInitialImport将始终为false,除非您访问数据库,强制打开它。

在进行测试之前,您需要打开(访问)数据库。

例子 :-

class MainActivity : AppCompatActivity() {

    var firstrun = false
    var myTableDao :MyTableDao? = null


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        Log.d("ROOMBUILD","Building Room Database")
        val db = Room.databaseBuilder(this,AppDatabase::class.java,"mydb")
            .allowMainThreadQueries()
            .addCallback(object: RoomDatabase.Callback()
            {
                override fun onCreate(db: SupportSQLiteDatabase) {
                    Log.d("ONCREATE","onCreate called.")
                    super.onCreate(db)
                    firstrun = true;
                }
            }
            )
            .build()
        Log.d("ROOMBUILD","Room database built")
        myTableDao = db!!.myTableDao()
        //myTableDao!!.getAll() //would also work assuming getAll is defined in the Dao
        db.openHelper.writableDatabase //<<<<<<<<<< Force open
        if (firstrun) {
            importData()
        }
         for (m in myTableDao!!.getAll()) {
             Log.d("MYTABLEINFO","Names is " + m.name + " ID is " + m.id)
         }
    }

    fun importData() {
        Log.d("IMPORTING","Data being imported")
        var mytable = MyTable()
        mytable.name = "MyData"
        myTableDao?.insert(mytable)
    }
}

结果

安装时:-

2019-11-08 10:36:18.629 D/ROOMBUILD: Building Room Database
2019-11-08 10:36:18.642 D/ROOMBUILD: Room database built
2019-11-08 10:36:18.664 D/ONCREATE: onCreate called.
2019-11-08 10:36:18.669 D/IMPORTING: Data being imported
2019-11-08 10:36:18.675 D/MYTABLEINFO: Names is MyData ID is 1

随后的运行:-

2019-11-08 10:37:07.759 D/ROOMBUILD: Building Room Database
2019-11-08 10:37:07.772 D/ROOMBUILD: Room database built
2019-11-08 10:37:07.789 D/MYTABLEINFO: Names is MyData ID is 1

推荐阅读