Android 房间嵌入字段未编译
Android Room Embedded Field Not Compiling
我正在尝试创建一个嵌入式字段。这是一个简单的例子,但我无法让这个简单的例子起作用。最终我需要有 3 个级别的嵌入式项目,但试图让这个测试用例工作。
@Entity(tableName = "userItemsEntity")
@Parcelize
data class Item(
var objecttype: String?,
@PrimaryKey(autoGenerate = false)
var objectid: Int?,
var subtype: String?,
var collid: Int?,
@Embedded
var name: Name?
) : Parcelable
@Parcelize
data class Name(
var primary: Boolean? = true,
var sortindex: Int? = null,
var content: String? = null) : Parcelable
当我尝试编译它时,它在 DAO 上抱怨 updateItem()
SQL error or missing database (no such column: name)
DAO 函数
@Query("UPDATE userItemsEntity SET " +
"objecttype=:objecttype, objectid=:objectid, subtype=:subtype, collid=:collid, name=:name " +
"WHERE objectid=:objectid")
fun updateItem(
objecttype: String?,
objectid: Int,
subtype: String?,
collid: Int?,
name: Name?)
原因是因为它说没有 name 列。 table 由列组成,根据 EMBEDDED class 的成员变量(即主要、排序索引和内容)。
即table 创建 SQL is/will 是 :-
CREATE TABLE IF NOT EXISTS `userItemsEntity` (`objecttype` TEXT, `objectid` INTEGER, `subtype` TEXT, `collid` INTEGER, `primary` INTEGER, `sortindex` INTEGER, `content` TEXT, PRIMARY KEY(`objectid`))
Room 知道在提取行时从这些列构建相应的 Name 对象。
所以你可以使用 :-
@Query("UPDATE userItemsEntity SET " +
"objecttype=:objecttype, objectid=:objectid, subtype=:subtype, collid=:collid, `primary`=:primary, sortindex=:sortindex, content=:content " +
"WHERE objectid=:objectid")
fun updateItem(
objecttype: String?,
objectid: Int,
subtype: String?,
collid: Int?,
primary: Boolean?,
sortindex: Int?,
content: String?
)
请注意,primary 是一个 SQLite 标记,因此用重音符括起来以确保它不被视为标记。否则你会得到:-
There is a problem with the query: [SQLITE_ERROR] SQL error or missing database (near "primary": syntax error)
但是,由于您使用的是基于主键 (objectid) 的 WHERE 子句,因此更新将仅适用于单个行,因此您可以简单地使用:-
@Update
fun update(item: Item): Int
- 显然函数的名称不必是 update 它可以是任何适合的有效名称。
- 这样做的好处不仅是更简单而且返回更新的行数(如果该行存在则为 1,否则为 0)
正在实施名称列
如果您想要一个 name 列并且该名称列包含一个 Name 对象。然后,由于 SQLite 没有 storage/column 对象类型,因此您不会嵌入名称 class.
你会 var name: Name?
有一个适当的 TypeConverter 将 Name 对象转换成 SQLite 适合的类型:-
文本(字符串),
REAL(浮点数,双精度...),
INTEGER (Long, Int ...) 或
BLOB (字节数组)).
通常使用字符串,通常使用 GSON 从对象转换为 JOSN 字符串。
SQlite 确实有 NUMERIC 类型。但是,Room 不支持它的使用。我相信是因为其他类型涵盖了所有类型的数据,而 NUMERIC 是 catch-all/default.
但是,使用对象的 JSON 表示会引入膨胀并从 SQL 方面降低转换数据的有用性。
例如说你有:-
@Entity(tableName = "userOtherItemsEntity")
@Parcelize
data class OtherItem (
var objecttype: String?,
@PrimaryKey(autoGenerate = false)
var objectid: Int?,
var subtype: String?,
var collid: Int?,
var name: OtherName?) : Parcelable
@Parcelize
data class OtherName(
var primary: Boolean? = true,
var sortindex: Int? = null,
var content: String? = null) : Parcelable
那么基础 table 确实有 name 列。 Room 生成的 CREATE SQL 将是:-
CREATE TABLE IF NOT EXISTS `userOtherItemsEntity` (`objecttype` TEXT, `objectid` INTEGER, `subtype` TEXT, `collid` INTEGER, `name` TEXT, PRIMARY KEY(`objectid`))
但是,您需要 TypeConverters,它可以是 :-
@TypeConverter
fun fromOtherName(othername: OtherName ): String {
return Gson().toJson(othername)
}
@TypeConverter
fun toOtherName(json: String): OtherName {
return Gson().fromJson(json,OtherName::class.java)
}
- 首先使用 Gson 将对象转换为 JSON 字符串,例如插入数据时
- 第二个将 JSON 字符串转换为 OtherName 对象。
使用嵌入名称的项目,然后数据将按照以下行存储:-
在转换带有 OtherName 的 OtherItem 时,数据(类似数据)将遵循 :-
在前者中,3 个名称列将占用大约 (1 + 1 + 12) = 16 个字节。
在后者中,OtherName 列(在使用时不考虑 Other 一词)将占用大约 55 个字节。
如果要将 OtherName 的组件包含在搜索中,后者可能需要更复杂且资源消耗更大的搜索。
- 例如
@Query("SELECT * FROM userItemsEntity WHERE
主要")
相对于 @Query("SELECT * FROM userOtherItemsEntity WHERE instr(name,'primary\":true') > 0")
我正在尝试创建一个嵌入式字段。这是一个简单的例子,但我无法让这个简单的例子起作用。最终我需要有 3 个级别的嵌入式项目,但试图让这个测试用例工作。
@Entity(tableName = "userItemsEntity")
@Parcelize
data class Item(
var objecttype: String?,
@PrimaryKey(autoGenerate = false)
var objectid: Int?,
var subtype: String?,
var collid: Int?,
@Embedded
var name: Name?
) : Parcelable
@Parcelize
data class Name(
var primary: Boolean? = true,
var sortindex: Int? = null,
var content: String? = null) : Parcelable
当我尝试编译它时,它在 DAO 上抱怨 updateItem()
SQL error or missing database (no such column: name)
DAO 函数
@Query("UPDATE userItemsEntity SET " +
"objecttype=:objecttype, objectid=:objectid, subtype=:subtype, collid=:collid, name=:name " +
"WHERE objectid=:objectid")
fun updateItem(
objecttype: String?,
objectid: Int,
subtype: String?,
collid: Int?,
name: Name?)
原因是因为它说没有 name 列。 table 由列组成,根据 EMBEDDED class 的成员变量(即主要、排序索引和内容)。
即table 创建 SQL is/will 是 :-
CREATE TABLE IF NOT EXISTS `userItemsEntity` (`objecttype` TEXT, `objectid` INTEGER, `subtype` TEXT, `collid` INTEGER, `primary` INTEGER, `sortindex` INTEGER, `content` TEXT, PRIMARY KEY(`objectid`))
Room 知道在提取行时从这些列构建相应的 Name 对象。
所以你可以使用 :-
@Query("UPDATE userItemsEntity SET " +
"objecttype=:objecttype, objectid=:objectid, subtype=:subtype, collid=:collid, `primary`=:primary, sortindex=:sortindex, content=:content " +
"WHERE objectid=:objectid")
fun updateItem(
objecttype: String?,
objectid: Int,
subtype: String?,
collid: Int?,
primary: Boolean?,
sortindex: Int?,
content: String?
)
请注意,primary 是一个 SQLite 标记,因此用重音符括起来以确保它不被视为标记。否则你会得到:-
There is a problem with the query: [SQLITE_ERROR] SQL error or missing database (near "primary": syntax error)
但是,由于您使用的是基于主键 (objectid) 的 WHERE 子句,因此更新将仅适用于单个行,因此您可以简单地使用:-
@Update
fun update(item: Item): Int
- 显然函数的名称不必是 update 它可以是任何适合的有效名称。
- 这样做的好处不仅是更简单而且返回更新的行数(如果该行存在则为 1,否则为 0)
正在实施名称列
如果您想要一个 name 列并且该名称列包含一个 Name 对象。然后,由于 SQLite 没有 storage/column 对象类型,因此您不会嵌入名称 class.
你会 var name: Name?
有一个适当的 TypeConverter 将 Name 对象转换成 SQLite 适合的类型:-
文本(字符串),
REAL(浮点数,双精度...),
INTEGER (Long, Int ...) 或
BLOB (字节数组)).
通常使用字符串,通常使用 GSON 从对象转换为 JOSN 字符串。
SQlite 确实有 NUMERIC 类型。但是,Room 不支持它的使用。我相信是因为其他类型涵盖了所有类型的数据,而 NUMERIC 是 catch-all/default.
但是,使用对象的 JSON 表示会引入膨胀并从 SQL 方面降低转换数据的有用性。
例如说你有:-
@Entity(tableName = "userOtherItemsEntity")
@Parcelize
data class OtherItem (
var objecttype: String?,
@PrimaryKey(autoGenerate = false)
var objectid: Int?,
var subtype: String?,
var collid: Int?,
var name: OtherName?) : Parcelable
@Parcelize
data class OtherName(
var primary: Boolean? = true,
var sortindex: Int? = null,
var content: String? = null) : Parcelable
那么基础 table 确实有 name 列。 Room 生成的 CREATE SQL 将是:-
CREATE TABLE IF NOT EXISTS `userOtherItemsEntity` (`objecttype` TEXT, `objectid` INTEGER, `subtype` TEXT, `collid` INTEGER, `name` TEXT, PRIMARY KEY(`objectid`))
但是,您需要 TypeConverters,它可以是 :-
@TypeConverter
fun fromOtherName(othername: OtherName ): String {
return Gson().toJson(othername)
}
@TypeConverter
fun toOtherName(json: String): OtherName {
return Gson().fromJson(json,OtherName::class.java)
}
- 首先使用 Gson 将对象转换为 JSON 字符串,例如插入数据时
- 第二个将 JSON 字符串转换为 OtherName 对象。
使用嵌入名称的项目,然后数据将按照以下行存储:-
在转换带有 OtherName 的 OtherItem 时,数据(类似数据)将遵循 :-
在前者中,3 个名称列将占用大约 (1 + 1 + 12) = 16 个字节。
在后者中,OtherName 列(在使用时不考虑 Other 一词)将占用大约 55 个字节。
如果要将 OtherName 的组件包含在搜索中,后者可能需要更复杂且资源消耗更大的搜索。
- 例如
@Query("SELECT * FROM userItemsEntity WHERE
主要")
相对于@Query("SELECT * FROM userOtherItemsEntity WHERE instr(name,'primary\":true') > 0")
- 例如