Room 数据库中的多对多关系。 Kotlin Junction 类被忽略
Posted
技术标签:
【中文标题】Room 数据库中的多对多关系。 Kotlin Junction 类被忽略【英文标题】:many-to-many relation in Room database. Kotlin Junction class ignored 【发布时间】:2020-05-11 14:27:07 【问题描述】:我有以下用于 Room 版本的 Kotlin 实体。 2.2.5。
父实体
@Entity(tableName = "ITEM",
indices = [Index(value = ["id"], unique = true), Index(value = ["code"], unique = true), Index(value = ["status"], unique = false)]
)
data class Item (
@PrimaryKey @ColumnInfo(name = "id") override val id: UUID = UUID.randomUUID(),
@ColumnInfo(name = "code") @NotNull val code: String,
@ColumnInfo(name = "valid") val valid: Boolean = true,
@ColumnInfo(name = "value") val value: Double?,
@ColumnInfo(name = "price") val price: Double?,
@ColumnInfo(name = "default_description") val defaultDescription: String?,
@ColumnInfo(name = "description") val description: String?
)
子实体
@Entity(tableName = "LOCATION",
indices = [Index(value = ["id"], unique = true), Index(value = ["code"], unique = true)]
)
data class Location (
@ColumnInfo(name = "id") @PrimaryKey override val id: UUID = UUID.randomUUID(),
@ColumnInfo(name = "code") val code: String,
@ColumnInfo(name = "latitude") val latitude: Double?,
@ColumnInfo(name = "longitude") val longitude: Double?,
@ColumnInfo(name = "default_description") val defaultDescription: String?
)
连接实体
@Entity(
tableName = "ITEM_LOCATION_L",
primaryKeys = [
"item_id", "location_id"
],
foreignKeys = [
ForeignKey(entity = Item::class, parentColumns = ["id"], childColumns = ["item_id"]),
ForeignKey(entity = Location::class, parentColumns = ["id"], childColumns = ["location_id"])
],
indices = [
Index("id"),
Index("item_id"),
Index("location_id")])
data class ItemLocationLink (
@ColumnInfo(name = "id") override val id: UUID = UUID.randomUUID(),
@ColumnInfo(name = "item_id") val itemId: UUID, /** Item ID - parent entity */
@ColumnInfo(name = "location_id") val locationId: UUID, /** Location ID - child entity */
@ColumnInfo(name = "quantity") val quantity: Double /** Quantity of the item in the referenced location */
)
结果分类
class ItemLocationRelation
@Embedded
lateinit var item: Item
@Relation(
parentColumn = "id",
entityColumn = "id",
associateBy = Junction(value = ItemLocationLink::class, parentColumn = "item_id", entityColumn = "location_id")
) lateinit var locations: List<Location>
DAO 接口
@Dao
interface ItemLocationLinkDao
@Transaction
@Query("SELECT * FROM ITEM WHERE id = :itemId")
fun getLocationsForItem(itemId: UUID): List<ItemLocationRelation>
数据库类型转换器
class DBTypesConverter
@TypeConverter
fun fromUUID(uid: UUID?): String?
if (uid != null)
return uid.toString()
return null
@TypeConverter
fun toUUID(str: String?): UUID?
if (str != null)
return UUID.fromString(str)
return null
@TypeConverter
fun fromDate(d: Date?): Long?
return d?.time
@TypeConverter
fun toDate(l: Long?): Date?
return if (l != null) Date(l) else null
当我调用 getLocationsForItem 时,我得到一个 ItemLocationRelation 实例,其中包含有效的 Item 但没有子对象。我检查了生成的代码,没有 Junction 类的迹象。生成的代码表现得好像它不是多对多关系,完全忽略了 Junction 类,我什至可以在关系的 @Junction 属性中指定一个假类,结果将完全相同,没有错误。
如果我向 DAO 类添加一个返回以下查询结果的函数:
select * from item
inner join item_location_l as link on link.item_id = item.id
inner join LOCATION as l on link.location_id = l.id
where item.id = '99a3a64f-b0e6-e911-806a-68ecc5bcbe06'
我按预期得到 2 行。所以 SQLite 数据库没问题。请帮忙。
【问题讨论】:
我没有看到您的代码存在明显问题(除了:1. 我没有得到关于 2 的数据类的某些字段的覆盖内容。目前尚不清楚 UUID 的 typeConverter 是什么你用过吗)。恐怕如果没有完整的回购,有人帮助你将是一项复杂的任务 顺便问一下,您手动检查过您的查询结果吗?最简单的方法 - 是在您的 item_id 上使用内部连接对所有 3 个表构建查询 嗨,Sergiy,UUID 的类型转换器将 UUID 转换为字符串并返回。它工作正常。我也尝试用 long 替换 UUID 无济于事。我按照您的建议尝试了查询,它工作正常。问题是生成的代码完全缺少 Junction 表,因为它只是一个一对多的关系。我在问题代码中添加了类型转换器 所以你说在你生成的DAO实现类中没有提到表“ITEM_LOCATION_L”(用文本搜索)? 我调试了代码,没有任何地方使用 ITEM_LOCATION_L 的迹象。我调试了自动生成的代码,它的行为就像关系是一对一的。我也尝试以这种方式更改连接:Junction(value = String::class, parentColumn = "item_id", entityColumn = "location_id"),强制 String 作为连接类。生成的代码完全相同,我没有收到任何错误。结果与之前完全相同...该项目很好,但它没有子对象,因为生成的代码使用项目 ID 进行搜索,而不是在 ITEM_LOCATION_L 中查询正确的 ID 【参考方案1】:所以,最后问题真的很微妙。由于某些原因,我无法解释我正在从事的项目有以下 gradle 设置(app gradle):
kapt "android.arch.persistence.room:compiler:2.2.5"
我把它换成了
kapt "androidx.room:room-compiler:2.2.5"
然后一切都很好。插件生成的硬编码查询现在包含 JOIN 并且可以正常工作....
【讨论】:
以上是关于Room 数据库中的多对多关系。 Kotlin Junction 类被忽略的主要内容,如果未能解决你的问题,请参考以下文章