Android:使用 room 创建的 SQLite 数据库在使用 sqlite-browser 打开时不显示任何表

Android: SQLite database created with room shows no tables when opening with sqlte-browser

我正在使用 Room Persistence Library 1.1.0。我可以使用 Android Studio 的设备文件资源管理器在 /data/data/<package_name>/databases/ 找到数据库文件。

它包含多个 tables,我可以使用 room-DAOs 毫无问题地访问 tables 的内容。然而,当用 sqlite-browser 打开时,显示没有 table.

可能是什么原因?是否可以在不从房间切换回旧 SQLiteOpenHelper 的情况下解决问题?

解决方案

要用sqlite-browser打开这样的数据库*,你需要复制所有三个文件。所有都必须在同一目录中。

* 如问题所述,数据库存储在多个文件中。


为什么是三个文件?

根据文档,从版本 1.1.0 开始,Room 使用 write-ahead logging 作为具有足够 RAM 的设备的默认日志模式,并在 API 级别 16 上使用 运行 或更高。在这个版本之前,所有设备都是 Truncatewrite-ahead loggingTruncate 相比具有不同的内部结构。


偶尔看看 SQLite 使用的临时文件 :

直到版本 1.1.0

自版本 1.1.0


如果您想将日志模式明确更改为Truncate,您可以这样做。但是,不推荐因为WALTruncate好很多。

public static void initialize(Context context) {
    sAppDatabase = Room.databaseBuilder(
            context,
            AppDatabase.class,
            DATABASE_NAME)
        .setJournalMode(JournalMode.TRUNCATE).build();
}


是否可以在不更改为 Truncate 的情况下将其移动到单个文件?

是的,是的。针对数据库查询以下语句。

pragma wal_checkpoint(full)

此处详细讨论

您可以使用 wal_checkpoint pragma 来触发 checkpoint,这会将 WAL 文件事务移回数据库。

        theRoomDb.query("pragma wal_checkpoint(full)", null)

        // the result
        // contains 1 row with 3 columns
        // busy, log, checkpointed
        Cursor cursor = theRoomDb.query("pragma wal_checkpoint(full)", null)

有关 pragma 参数值和结果的更多详细信息,请参阅 PRAGMA Statements

如果 WAL 未启用,则 pragma 不执行任何操作。 对了,我是用Room 1.1.1测试的,默认没有使用WAL模式,只好开启了。

将 AndroidStudio 中设备文件资源管理器中的所有三个文件复制到您的 PC 目录,并在 SQLite 数据库浏览器中打开 db 文件 (http://sqlitebrowser.org)。确保所有三个文件都在同一个文件夹中。

房间数据库导出和导入解决方案

我在我的一个项目中遇到了同样的问题,我花了两天时间来解决这个问题。

解决方案

Don't create multiple instance for Room library. Multiple instance creating all the problems.

我的应用程序

class MyApplication: Application() 
{

companion object {
    lateinit var mInstanceDB: AppDatabase
}

override fun onCreate() {
    super.onCreate()
    mInstanceDB = AppDatabase.getInstance(this)
}
}

AppDatabase

fun getInstance(context: Context): AppDatabase 
{

if (sInstance == null) {

    sInstance = Room.databaseBuilder(context.applicationContext,AppDatabase::class.java, "database").allowMainThreadQueries().build() 

            return sInstance!!
}
}

现在在任意数量的 activity 或片段中使用此实例,就像那样

{
    var allcustomer = MyApplication.mInstanceDB.customerDao.getAll()
}

导出和导入使用这个库

implementation 'com.ajts.androidmads.sqliteimpex:library:1.0.0'

Github link