如何使用 Android Room Persistence Library 将 Column 注释为 NOT NULL
Posted
技术标签:
【中文标题】如何使用 Android Room Persistence Library 将 Column 注释为 NOT NULL【英文标题】:How to annotate Column as NOT NULL using Android Room Persistence Library 【发布时间】:2017-11-08 18:20:41 【问题描述】:我的数据类是这样的
@Entity(tableName = "items")
data class Item(
@ColumnInfo(name = "name") var name: String = "",
@ColumnInfo(name = "room") var room: String = "",
@ColumnInfo(name = "quantity") var quantity: String = "",
@ColumnInfo(name = "description") var description: String = "",
@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = "id") var id: Long = 0
)
Room 使用 SQLite,并且 SQLite 在其数据库中支持 NOT NULL 列。我尝试使用 @NonNull 注释列,但没有效果。
有没有办法使房间数据库中的列不能为空?
【问题讨论】:
默认不是not null
?因为我也在研究房间持久性库,并且不小心将 null 发送到数据库,所以它触发了异常。
我得到了一些空字段,比如空字符串,它工作正常,所以我猜不是这样
那你的问题是什么?
【参考方案1】:
对于 Java,您应该使用 @android.support.annotation.NonNull
进行注释
不要与@io.reactivex.annotations.NonNull
混淆
【讨论】:
你拯救了我的一天! 如果我们需要将 RxJava 与 Room 一起使用,那么在创建实体时我们应该导入哪个? Ishwor Khanal,同样的@android.support.annotation.NonNull,rx 的注解主要用于内部目的【参考方案2】:为了确定 NOT NULL 的确切注释,我查看了此链接提供的所有注释列表:android.arch.persistence.room,但找不到任何相关注释:
我的假设是,由于您使用的是 Kotlin,它默认将 var 视为非可选的,因此您声明的所有属性都不是 NULL。为了将 var 声明为可选,您可能必须使用 ?运算符,下面是一个例子:
var name: String // NOT NULL
var name: String? // OPTIONAL
根据评论更新:
我猜你对 NULL 和空字符串感到困惑。 NULL 表示没有值,在共享代码中,您为每个列提供了一个默认值,该列是一个空字符串并且不等于 NULL,因此即使您可能没有为该属性提供值,它默认分配一个给它的空字符串。
尝试删除属性的赋值运算符和 RHS 值,然后插入记录而不为该属性赋值,您应该会得到相应的错误。
基本上,转换下面的语句:
@ColumnInfo(name = "name") var name: String = ""
到
@ColumnInfo(name = "name") var name: String
【讨论】:
我对数据库中 NOT NULL 的理解意味着它不能是空字段,它需要分配一个值,以便将空字符串 "" 视为 NULL。在 kotlin 中,字符串意味着它分配的对象不为空,在我的情况下默认为空字符串。我只希望我的数据库在分配空字符串时抛出异常。我猜你不能在房间里这样做 我会将其标记为正确,因为它澄清了我在空字符串和 null 之间的混淆。但是,在我的特殊情况下,您建议的转换语句(第二个)不可编译,因为 Room 需要默认构造函数,并且为此每个参数都必须具有默认值。但是感谢您的帮助! 谢谢,最初,这个答案对我不起作用,因为我将变量的范围设置为private
。
谢谢。使用NonNull
注释+ 设置没有赋值的属性也为我解决了这个问题@Devarshi
"它需要分配一个值,以便空字符串 "" 将被视为 NULL" 这是不正确的。空字符串不为空。空为空。空字符串是长度为 0 的字符串对象。【参考方案3】:
对于 Java,我在 @ColumnInfo
之后使用了 @NonNull
:
@ColumnInfo(name = "column_name")
@NonNull private String str;
确保您在类中导入了正确的库:
import android.support.annotation.NonNull;
【讨论】:
请注意,原始类型(int、long 等)总是被认为是 NonNull,您不必像这样对它们进行注释。 @BeerMe,你知道它记录在哪里吗?我刚刚在this article 中发现了对原始类型管理的提及。似乎浮点类型的处理方式不同,默认情况下可以为空。 @shield,我手边没有实际的文档,但这个答案总结得很好:***.com/a/11047335/295028 另外,我在您的链接文章中没有看到任何对浮点类型的引用,但它确实说“所有原始类型在 Room 中默认为非 null”。 @BeerMe,谢谢。我关于浮点类型的错误。在我查看的示例中,列类型不是原始的。它被声明为浮点数,而不是浮点数,因此默认情况下可以为空。【参考方案4】:对使用 Kotlin 的人的补充回答:
请注意,将类型标记为非可选会自动使其不为空(可选类型不会这样做)。
您可以在数据库中使用@Database(exportSchema = true)
生成的架构中检查它。
例如我有这样的事情:
@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`)
)"
(注意:这里的日期类型是Int
,UUID 是字符串,因为我在其他地方使用了转换器)
【讨论】:
【参考方案5】:作为实际表约束的变通方法,您可以使用单个方法 TypeConverter 类来确保您的 String 成员不为空。
例如,对于非空字符串,您可以使用:
public class RoomConverterNullString
@TypeConverter
public static String fromNullToString(String value)
if (value == null)
return "";
else
return value;
当然可以这样简化:
public class RoomConverterNullString
@TypeConverter
public static String fromNullToString(String value)
return (value == null) ? "" : value;
你可以这样使用它:
@TypeConverters(RoomConverterNullString.class)
public String stringMember;
当值为空时,任何赋值和更新/插入操作都将存储一个空字符串值,并且任何检索都会强制将空值转换为空字符串。
您可以对其他类型以及您希望拥有的任何默认值执行此操作。
【讨论】:
以上是关于如何使用 Android Room Persistence Library 将 Column 注释为 NOT NULL的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Android Room 从数据库中获取一行? [复制]
如何在android中使用Room Library fts4查询整个表
Android:如何使 Kotlin 中所有对象列表的类型转换器(用于 Room)通用
使用带有 Android 的 Room 使用 UUID 作为主键