仅向多个表的主键添加 @NonNull 注释的房间迁移

Posted

技术标签:

【中文标题】仅向多个表的主键添加 @NonNull 注释的房间迁移【英文标题】:Room migration that only adds a @NonNull annotation to primary key on several tables 【发布时间】:2020-02-09 04:38:48 【问题描述】:

我正在将应用程序从定位 sdk 25 升级到定位 sdk 29,我房间数据库中的所有表都有 @PrimaryKey 注释,但没有使用 @NonNull 注释.现在我的目标是 sdk 29,房间需要 @NonNull 注释,不幸的是这会导致我的应用程序在启动时崩溃,除非我重新安装。

如果没有全新安装会导致错误

java.lang.RuntimeException: An error occurred while executing doInBackground()
    at android.os.AsyncTask$3.done(AsyncTask.java:318)
    at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:354)
    at java.util.concurrent.FutureTask.setException(FutureTask.java:223)
    at java.util.concurrent.FutureTask.run(FutureTask.java:242)
    at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:243)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
    at java.lang.Thread.run(Thread.java:761)
 Caused by: java.lang.IllegalStateException: attempt to re-open an already-closed object: SQLiteDatabase:

我认为这是因为我的数据库必须迁移,因为它可以在全新安装上运行。

到目前为止,我已经找到了一些有用的堆栈溢出答案,例如 one。

但这需要我重写数据库中的每个表,并确保将所有索引都带过来。我不想这样做,因为我确信我会错过一些东西,并且会产生多个错误。

有没有更简单的方法来进行房间迁移,我只需将@NonNull 注释添加到我的所有主键?

另外,我看到有人提到从 SQLite 表中获取架构,这会将所有索引封装到查询中,但我不知道如何在迁移中获取该架构。

添加 NonNull 标签后的示例类:

@Entity(tableName = "FavoriteTrip"
    , indices =  @Index("tripPlanId") 
    , foreignKeys = @ForeignKey(entity = TripPlan.class, parentColumns = "id", childColumns = "tripPlanId"))
public class FavoriteTrip 

    @PrimaryKey @NonNull
    private String id = UUID.randomUUID().toString();

【问题讨论】:

【参考方案1】:

有没有更简单的方法来进行房间迁移,我只需将@NonNull 注释添加到我的所有主键?

我相信有很多但实际上并没有玩过它(只是快速尝试一下,发现您仍然需要创建实体以正确匹配表格)。即让 ROOM 转换数据库(您可能必须删除 room_master_table),即使用最近添加的 createFrom 方法之一。

createFromAsset -createFromFile

这些会将数据库转换为房间可以接受的数据库,但据我所知,它不会创建实体,由于预期...... .... 发现 .... 很难阅读。

另一个选项是我一直在使用的东西,它可以转换数据库并另外生成基本的实体/Dao 和数据库代码 (Java)。这个工具可以在RoomExistingSQLiteDBConverter找到,它链接了github上的源代码。

作为一个非常快速的概述,

:-

    您运行应用程序(可能在 AS 模拟器中,尽管可能在真实设备上)。

    将数据库复制到公共外部存储中的任何(bar 1 保留文件夹)文件夹中(在应用程序运行之前或运行时,如果是后者则单击刷新按钮)。

    查看列出的各种组件,了解潜在的突出问题。 满意后点击转换按钮。 复制准备好导入的数据库(通常作为资产到资产文件夹中)到正在开发/更改的应用程序。 将代码复制到应用程序的相应文件夹中。 编辑代码以引入适当的导入。 编写代码以从资产文件夹中复制数据库。 测试。

【讨论】:

以上是关于仅向多个表的主键添加 @NonNull 注释的房间迁移的主要内容,如果未能解决你的问题,请参考以下文章

一张表多个字段是另一张表的主键,关联查询语句

conn.GetSchema 查找表的主键 - MsAccess

如何在 C# 中获取 Ms Access 表的主键

SQL查询查找表的主键?

Postgres:更新所有表的主键序列

请问SQL server 中的主键和外键的作用