会议室数据库:NOT NULL约束删除失败

时间:2019-09-24 09:28:31

标签: android sqlite android-room

我有以下实体SessionLabel

@Entity(
    foreignKeys =
    @ForeignKey(
            entity = Label.class,
            parentColumns = {"id", "archived"},
            childColumns = {"labelId", "archived"},
            onUpdate = CASCADE,
            onDelete = SET_DEFAULT))
    public class Session {

    @PrimaryKey(autoGenerate = true)
    public long id;

    @Nullable
    public String label = null;

    public boolean archived = false;
}

@Entity(primaryKeys = {"id", "archived"})
public class Label {

    @NonNull
    public String id;

    public boolean archived = false;
}

在删除附加到Label的{​​{1}}时,我得到的是Session的{​​{1}}。

我在这里做什么错了?

2 个答案:

答案 0 :(得分:2)

我认为问题在于使用public boolean archived = false;中的布尔类型。

由于 boolean 是Java主要类型,因此它具有隐式 @NonNull (表是使用NOT NULL约束创建的)

在“房间”中,您无法(我相信)设置在SQLite表中生成的默认值,因此当使用onDelete SET_DEFAULT时,默认值将为 NULL ,因为尚未设置实际的默认值

  • Note Room现在使用defaultValue()批注中的@ColumnInfo支持默认值。

  • 使用= false不会影响实际的SQLite表,即,如果使用 Boolean ,则列定义将是labelId INTEGER而不是labelId INTEGER DEFAULT 0。 / p>

假设NULL是可接受的,则可以使用 Boolean (对象)而不是boolean(主要类型)。对象可以为空。

即在会话中使用

public Boolean archived = false;

视觉外植:-

以下是Room为会话实体生成的代码,但使用:-

添加了附加列
.........
public boolean archived = false;
public Boolean other_archived = false; //<<<<<<<<<< ADDED
........

房间生成的代码:-

CREATE TABLE IF NOT EXISTS `Session` (
    `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, 
    `label` TEXT, 

    `archived` INTEGER NOT NULL, /*<<<<<<<<<< boolean so NOT NULL */ 
    `other_archived` INTEGER, /*<<<<<<<<<< Boolean so no NOT NULL */
    FOREIGN KEY(`label`, `archived`) REFERENCES `Label`(`id`, `archived`) ON UPDATE CASCADE ON DELETE SET DEFAULT)

额外

如果您希望Session表中的存档列为0(假),则必须修改该表。这将需要

  1. 创建一个替换表,除了标签列定义为label INTEGER DEFAULT 0(即添加DEFAULT 0)之外,其他相同
  2. 将数据从“会话”表复制到替换表中,例如INSERT INTO replacement_Session SELECT * FROM Session;
  3. 重命名会话表。
  4. 将替换表重命名为Session。
  5. 如果高兴,请删除重命名的Session表。

或者(我认为),您可以使用AFTER UPDATE TRIGGER将NULL更改为0(假)。

这两个选项都必须在Room之外或在RoomDatabase构建之前完成。

答案 1 :(得分:0)

参考this。如果您使用 Kotlin 进行编码,为了使模型字段可以为空,请不要使用 @Nullable 而是通过使用“?”使字段可以为空。 以下字段不可为空。

@Entity(tableName = "books")
data class Book(
    @PrimaryKey
    val id: Int,
    val title: String,
    val description: String,
    val info: String,
    val type: Int,
    val url: String
)

但以下字段可以为空:

@Entity(tableName = "books")
data class Book(
    @PrimaryKey
    val id: Int,
    val title: String?,
    val description: String?,
    val info: String?,
    val type: Int,
    val url: String?
)