如何为使用房间自动迁移创建的新列的现有行设置默认值?

Arp*_*kla 6 sql android database-migration kotlin android-room

我有一个包含几列的 Room SQL 表。我想向其中添加一列包含布尔值。为了将我的数据库迁移到这个新架构,我尝试使用 Room Auto-Migrations。我的问题是如何更新表中的现有行以获得false这个新添加的列的值?我是否必须通过更改表并将默认值插入到所有行来回退到编写手动迁移?

Mik*_*keT 6

我的问题是如何更新表中的现有行以使这个新添加的列的值为 false?

使用@ColumnInfodefalutValue例如实体中的列。

@ColumnInfo(defaultValue = "0") 
Run Code Online (Sandbox Code Playgroud)

我是否必须通过更改表并将默认值插入到所有行来回退到编写手动迁移?

然后,这应该在自动迁移时添加带有默认值子句的列。

  • 我相信(如果没记错的话)如果您不编写默认值,那么自动迁移将由于新列缺少默认值而失败。

额外的

如果您想使用默认值插入,您将无法@Insert在使用 @Dao 注释的相应接口/asbstract 类中使用便捷注释,而必须使用列出@Query省略要使用的列的列默认值,并且具有指定命名列的值的 VALUES 子句。

例如,对于具有 3 列的表,columna、columnb 和columnc;其中,columnc 指定了 DEFAULT,则插入函数可能类似于:-

@Query("INSERT INTO the_table (columna,columnb) VALUES(:valueForColumnA,:valueForColumnB);")
fun insertWithDefaultValueForColumnC(valueForColumnA: TheType,valueForColumnB: TheType): Long
Run Code Online (Sandbox Code Playgroud)
  • 请注意,以上是原则代码,尚未编译、测试或运行,因此可能包含一些错误。

补充评论

我尝试 @ColumnInfo(defaultValue = "1") 和 @ColumnInfo(defaultValue = "true") 将默认值设置为 true。但这没有用。

defaultValue = "1"defaultvalue = "0"做工作 (1 为真,0 为假)

但是default = "false"还是default = "true" 不能按预期工作。他们会得到类似的结果default = "whatever...."

也许是一个错误,也许是 Room 的问题。后者发生的情况是,它们作为字符串(SQLite 中的 TEXT)传递,因此实际上是这样插入的,即使列已被定义为布尔值。由于任何列都可以存储任何类型的灵活性,SQLite 允许使用此类值。

考虑以下实体:-

@Entity
data class Example1(
    @PrimaryKey
    val id: Long? = null,
    val name: String,
    /*
     ADDITIONS FOR V2
     */
    @ColumnInfo(defaultValue = "1")
    val b1: Boolean,
    @ColumnInfo(defaultValue = "0")
    val b2: Boolean,
    @ColumnInfo(defaultValue = "false")
    val b3: Boolean,
    @ColumnInfo(defaultValue = "true")
    val b4: Boolean
)
Run Code Online (Sandbox Code Playgroud)
  • 其中添加 b1-b4 并在运行版本 1 时存在 10 行时完成自动迁移,在运行版本 2 时运行另外 10 行并添加另外 10 列,如下所示:-

      db = TheDatabase.getInstance(this)
      dao = db.getAllDao()
      for (i in 1..10) {
          dao.insert(Example1(name = "V${DATABASE_VERSION}_$i", b1 = true, b2 = true, b3 = true, b4 = true))
      }
    
      for(e: Example1 in dao.getAllExample1s()) {
          Log.d("DBINFO","Name is ${e.name} id id ${e.id} " +
          /*" ADDED COL = There Aren't any" */
          " B1=${e.b1} B2=${e.b2} B3=${e.b3} B4=${e.b4}"
          )
      }
    
    Run Code Online (Sandbox Code Playgroud)

第二次运行的结果是:-

2022-01-05 09:41:43.503 D/DBINFO: Name is V1_1 id id 1  B1=true B2=false B3=false B4=false
2022-01-05 09:41:43.504 D/DBINFO: Name is V1_2 id id 2  B1=true B2=false B3=false B4=false
2022-01-05 09:41:43.504 D/DBINFO: Name is V1_3 id id 3  B1=true B2=false B3=false B4=false
2022-01-05 09:41:43.504 D/DBINFO: Name is V1_4 id id 4  B1=true B2=false B3=false B4=false
2022-01-05 09:41:43.504 D/DBINFO: Name is V1_5 id id 5  B1=true B2=false B3=false B4=false
2022-01-05 09:41:43.504 D/DBINFO: Name is V1_6 id id 6  B1=true B2=false B3=false B4=false
2022-01-05 09:41:43.504 D/DBINFO: Name is V1_7 id id 7  B1=true B2=false B3=false B4=false
2022-01-05 09:41:43.504 D/DBINFO: Name is V1_8 id id 8  B1=true B2=false B3=false B4=false
2022-01-05 09:41:43.504 D/DBINFO: Name is V1_9 id id 9  B1=true B2=false B3=false B4=false
2022-01-05 09:41:43.504 D/DBINFO: Name is V1_10 id id 10  B1=true B2=false B3=false B4=false
2022-01-05 09:41:43.504 D/DBINFO: Name is V2_1 id id 11  B1=true B2=true B3=true B4=true
2022-01-05 09:41:43.504 D/DBINFO: Name is V2_2 id id 12  B1=true B2=true B3=true B4=true
2022-01-05 09:41:43.505 D/DBINFO: Name is V2_3 id id 13  B1=true B2=true B3=true B4=true
2022-01-05 09:41:43.505 D/DBINFO: Name is V2_4 id id 14  B1=true B2=true B3=true B4=true
2022-01-05 09:41:43.505 D/DBINFO: Name is V2_5 id id 15  B1=true B2=true B3=true B4=true
2022-01-05 09:41:43.505 D/DBINFO: Name is V2_6 id id 16  B1=true B2=true B3=true B4=true
2022-01-05 09:41:43.505 D/DBINFO: Name is V2_7 id id 17  B1=true B2=true B3=true B4=true
2022-01-05 09:41:43.505 D/DBINFO: Name is V2_8 id id 18  B1=true B2=true B3=true B4=true
2022-01-05 09:41:43.506 D/DBINFO: Name is V2_9 id id 19  B1=true B2=true B3=true B4=true
2022-01-05 09:41:43.506 D/DBINFO: Name is V2_10 id id 20  B1=true B2=true B3=true B4=true
Run Code Online (Sandbox Code Playgroud)

前 10 行已应用默认值,如下所示:-

  • 根据编码默认值,b1 为 true,即 1 = true
  • 根据编码默认值,b2 为 false,即 0 = false
  • b3 和 b4 为 false,因为该值是 TEXT/STRING(如下所示),无法转换为 Int,因此不会发生异常,而是转换为 0,从而为 false。

如果使用应用程序检查来查看它显示的数据:-

在此输入图像描述

如果再次使用应用程序检查/数据库检查器并使用以下查询表SELECT *,typeof(b1),typeof(b2),typeof(b3),typeof(b4) FROM example1;:-

在此输入图像描述

即自动迁移之前存在的 10 行的 b3 和 b4 列保存为文本。