Room Persistence Library 没有“NOT NULL”和“UNIQUE”约束条件。

23

在使用Room持久性库时,我发现没有一种方法可以对数据类字段设置NOT NULL和UNIQUE约束。SQLite是否支持这些约束呢?在迁移旧数据库中使用这些约束时会有问题吗?有人能否针对此问题提出建议吗?


支持唯一约束,检查索引和唯一性,请参考 https://developer.android.com/topic/libraries/architecture/room.html。 - USKMobility
4个回答

51
我了解到没有一种方法可以在数据类字段上设置NOT NULL和UNIQUE约束。对于实体字段,使用@NonNull注释将导致该字段的列应用NOT NULL。在@Index上使用unique=true将强制执行唯一性约束,但是,您正确地指出,除通过索引外,不支持在列上进行普通的UNIQUE约束。
迁移旧数据库是否会有问题? Room不是设计用于支持现有数据库结构,特别是在当前的alpha状态下。随着时间的推移,我期望Room将支持更高比例的SQLite功能,但如果它最终达到100%,我会感到惊讶。

谢谢您对Room库了解这么多。我有很多问题,而总是从您的回答中得到解决方案:D - techfly
1
我有点困惑。请问我需要从哪个包中导入@NonNull注解? 是android.support.annotation还是javax.annotation - Ifta
1
@Ifta:我会使用android.support.annotation,但希望Room注解处理器可以检查两者。 - CommonsWare
3
Kotlin 版本 @Entity(tableName = "some_table", indices = [ Index(value = ["some_field"], unique = true) ]) 的翻译如下:实体注解 @Entity 的参数包括表名 tableName 和索引 indices,其中索引通过数组的形式传入。在索引数组中,可以使用 Index 注解来指定需要建立索引的字段及其属性,如是否唯一等。在这个例子中,我们指定了一个名为 "some_field" 的字段需要创建唯一索引。 - Vlad

8

关于在使用Kotlin时的NOT NULL的补充说明:

请注意,将类型标记为非可选类型将自动使其非空(而可选类型则不会这样做)。

您可以通过在数据库上使用@Database(exportSchema = true)来检查Room生成的模式。

例如,我有这样的代码:

@Entity(tableName = "messages")
data class Message (
        @PrimaryKey
        val messageId: UUID = UUID.randomUUID(),
        val date: Date = Date(),
        val receivedDate: Date? = null
)

在生成的架构中,我可以读到:

"CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`messageId` TEXT NOT NULL, `date` INTEGER NOT NULL, `receivedDate` INTEGER, PRIMARY KEY(`messageId`))"

(注意:这里的Date类型是一个Int,UUID是一个字符串,因为我在其他地方使用了转换器)

(注:此处的Date类型是一个Int,UUID是字符串,因为我在其他地方使用的转换器)


1

对于可空字段,您可以使用包装器原始类型Java。例如,在您的Room表中使用Integer实例int。 就像在包装器原始类型java中一样,这可以是null,但原始类型类不能为null。并且在生成使用notNull = true的原始字段的SQL代码时,但是当使用Integer生成SQL代码时,使用notNull = false。


1
如果您有多个需要标记为唯一的项目,并且基于此要插入数据库,则可以使用复合主键。 对于非空值,Room提供了"@NonNull"注释,该注释添加在字段上表示该字段不能为空。 在下面的示例中,每个班级中的学号是唯一的,但是两个不同的班级可能具有相同的学号。因此,我们可以使用班级和学号作为复合主键,并以唯一方式插入数据库。 示例:
    @Entity(primaryKeys = {"rollNumber", "class"})   
    class Student {
       @NonNull
        private int rollNumber;
        private String firstName;
        private String lastName;
        private int class;
        } 

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接