【问题标题】:room migration using existing boolean column types使用现有布尔列类型进行房间迁移
【发布时间】:2018-06-24 00:36:33
【问题描述】:

到目前为止我发现了什么

在编译期间处理所有@entity 注释的类,并生成数据库类的实现。然后在访问数据库之前,调用这个生成的类的 validateMigration 方法。此 validateMigration 方法通过原始查询验证现有数据库架构

PRAGMA table_info mytable name

(参见 android.arch.persistence.room.util.TableInfo.java 的 L208)

现在的问题

我的 sqlite3 数据库有一些列类型为 BOOLEAN 的列。 (其中 slqite 内部处理为 int)。现在当我创建房间实体时说

public someEntity {
     @columnInfo(name="someName")
     public Boolean myValue;
}

房间的创建表查询将是

Create Table someEntity ( myValue INTEGER)

当我们使用PRAGMA table_info someEntity 查询现有数据库时,我们得到

1|myValue|BOOLEAN|0||0

如上所述,room 通过比较字段名称、列类型等来验证(从 sqlite 到 room)迁移。由于列类型不匹配(BOOLEAN 和 INTEGER),它会引发错误,指出迁移失败。

任何人都可以提出解决方法吗?我们可以在 sqlite 中创建 BOOLEAN 列类型吗? (另外,我们不能更改/更改现有表的列类型。)

PS:我也看到了与 VARCHAR 类似的问题 - Using an existing VARCHAR column with Room

【问题讨论】:

  • 感谢您的链接。我遇到了你在我提到的另一个问题上发布的issuetracker.google.com/issues/64822502。看起来这个问题自 17 年 8 月以来就一直存在。除了创建新表之外,您可以建议任何解决方法吗? @CommonsWare
  • “另外,我们不能更改/更改现有表的列类型”——您可以使用现有结构创建一个临时表,将数据复制到其中,删除真实表,重建具有 Room-approved 类型的真实表,然后将数据复制回来。这是我目前知道的唯一解决方法。
  • @CommonsWare 我在使用迁移将数据从 sqlite 复制到房间表时遇到了这个问题。当我不向迁移内部的创建查询添加非空值时,创建查询和具有布尔/整数的实体不匹配并引发错误。如果我在创建查询中添加 not null,我会收到错误 "android.database.sqlite.SQLiteConstraintException: NOT NULL constraint failed:" 。我已经交叉检查了旧表,这些列都没有空值。它们都填充有默认值或插入值。有什么建议我可能做错了吗?
  • @AshishKanswal:我只能建议您提出一个单独的 Stack Overflow 问题,并提供 minimal reproducible example

标签: java android sqlite android-room


【解决方案1】:

SQLite 没有布尔数据类型。 Room 将其映射到 INTEGER 列,将 true 映射到 1 并将 false 映射到 0。 我认为下面的代码可以工作

database.execSQL("ALTER TABLE xyz_table ADD COLUMN abc INTEGER DEFAULT 0");

它是无证的。

【讨论】:

    【解决方案2】:

    使用DEFAULT 值和NOT NULL 定义新属性newAttribute 的迁移。

    代码

    database.execSQL("ALTER TABLE tableName ADD COLUMN newAttribute INTEGER DEFAULT 0 NOT NULL")

    完整代码

    @Database(entities = arrayOf(ModelName::class), version = 2)
    @TypeConverters(Converters::class)
    abstract class DatabaseName : RoomDatabase() {
    
        abstract fun daoName(): DaoName
    
        companion object {
    
            private var INSTANCE: DatabaseName? = null
    
            fun getAppDatabase(context: Context): DatabaseName {
                if (INSTANCE == null) {
                    INSTANCE = Room.databaseBuilder(context.applicationContext,
                            DatabaseName::class.java, DATABASE_NAME)
                            .addMigrations(MIGRATION_1_2)
                            .build()
                }
                return INSTANCE as DatabaseName
            }
    
            val MIGRATION_1_2: Migration = object : Migration(1, 2) {
                override fun migrate(database: SupportSQLiteDatabase) {
                    database.execSQL("ALTER TABLE tableName ADD COLUMN newAttribute INTEGER DEFAULT 0 NOT NULL")
                }
            }
        }
    
    }
    

    【讨论】:

    • 感谢您的回答 :) 为我节省了很多时间!
    猜你喜欢
    • 2020-02-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-26
    • 1970-01-01
    • 2022-01-13
    • 2019-02-12
    相关资源
    最近更新 更多