我如何在 Android Room 中使用 SQLite 的 DEFAULT <a_value> 等价物

How do I utilise the equivalent of SQLite's DEFAULT <a_value> in Android Room

请注意,这是有意 Q and A 到 show/explain 的区别,在使用 Room 时,对象的默认实例化(构造)值和 SQLite 的 DEFAULT 子句之间以及如何使用或者

在 Room 中,您可以编写 @ColumInfo(defaultValue = "a_default_value") 例如 (以及后续演示)

@Entity
data class User(
    @PrimaryKey
    val userId: Long?, /* allow null for auto assigned ID */
    @ColumnInfo(defaultValue = "1000")
    val flag1: Int = 0,
    @ColumnInfo(defaultValue = "10000")
    val flag2: Int = 10,
    @ColumnInfo(defaultValue = "default from column DEFAULT clause")
    val otherData: String? = "default from object's default value"
)

思道:-

@Insert
abstract fun insert(user: User): Long

然后使用 :-

dao.insert(User(null))

导致对象的默认值按照

分配
User is 1 Flag1 is 0 Flag2 is 10 OtherData is default from object's default value

如果使用:-

dao.insert(User(100, otherData = "Blah"))

然后结果是相似的,除了 Blah 被分配给 otherData :-

User is 100 Flag1 is 0 Flag2 is 10 OtherData is Blah

那么使用 defaultValue 值呢?如何? (虽然没那么多use/difference)

您可以使用列定义的默认值(在 Room 中也称为 defaultValue="a_default_value")。

请注意,在某些情况下对此进行编码可能 necessary/advantageous,例如在迁移时,现有行具有 suitable 值。

要在通过 Room 插入时使用默认值(假设由于某种原因您不能使用对象的默认值)您必须使用定义特定列的插入,除了要使用 DEFAULT 的列(即 table 中编码的默认值).

一个例外是,如果每一列都是默认的 (在上面可能是因为 userid 列是 rowid 的别名,因为它是使用 userid INTEGER PRIMARY KEY 有效定义的)

  • 如果您使用 @ColumnInfo(defaultValue = ?),则 table 中的列将以 the_column_name the_columntype DEFAULT '?' 定义,例如问题中的实体会导致创建 table使用

:-

CREATE TABLE IF NOT EXISTS `User` (
    `userId` INTEGER, 
    `flag1` INTEGER NOT NULL DEFAULT 1000, 
    `flag2` INTEGER NOT NULL DEFAULT 10000, 
    `otherData` TEXT DEFAULT 'default from column DEFAULT clause', 
    PRIMARY KEY(`userId`))
  • 上面的 SQL 已经在编译后从 生成的 java 中提取出来,Room 基于实体生成。

例如,如果需要使用所有定义的默认值(flag1、flag2 和其他数据列)插入一行,则仅应指定 userId 列并提供一个值。 SQL 将是 INSERT INTO user (userid) VALUES(the_userid_value).

  • 根据

    • INSERT INTO table VALUES(...);第一种形式(带“VALUES”关键字)在现有 table 中创建一个或多个新行。如果省略了 table-name 之后的列名列表,则每行中插入的值数必须与 table 中的列数相同。在这种情况下,从 VALUES 列表的每个项计算最左边的表达式的结果被插入到每个新行的最左边的列中,对于每个后续表达式等等。如果指定了列名列表,则 VALUE 列表的每个项中的值数必须与指定列数匹配。新行的每个命名列都填充了计算相应 VALUES 表达式的结果。 Table 未出现在列列表中的列使用默认列值(指定为 CREATE TABLE 语句的一部分)填充,如果未指定默认值,则使用 NULL .

    • https://sqlite.org/lang_insert.html

对于这样的 SQL 房间表示应该使用 @Query 而不是根据

@Insert

对于上述实体,这可能是:-

@Query("INSERT INTO user (userid) /*<<<<< defined columns all other columns will be defaults */ VALUES(:userid)")
abstract fun insert(userid: Long)

例外情况是,如果所有列都是默认值,在这种情况下将使用 INSERT INTO the_table DEFAULT VALUES,例如:-

@Query("INSERT INTO user DEFAULT VALUES")
abstract fun insert(): Long

然后付诸实践:-

    dao.insert(10000) /* @Query insert to demo defaultValue */
    dao.insert() /* special using INSERT INTO table DEFAULT VALUES */

结果:-

User is 10000 Flag1 is 1000 Flag2 is 10000 OtherData is default from column DEFAULT clause
User is 10001 Flag1 is 1000 Flag2 is 10000 OtherData is default from column DEFAULT clause

即Flag1、Flag2 和 OtherData 使用 table 定义的默认值,对于后者,用户 ID 也默认为生成的用户 ID(通常比现有的最高用户 ID 大 1,但也可能不是)。