Room - 不按 id 过滤时,1-N 关系中的查询结果不正确

问题描述 投票:0回答:1

我有以下结构来定义与朋友的会议。首先我有我的

Friend
实体

@Entity(tableName = Friend.TABLE_NAME)
data class Friend(
    @PrimaryKey(autoGenerate = true)
    val id: Int? = null,
    val alias: String? = null
) {
    companion object {
        const val TABLE_NAME = "friends"
    }
}

还有我的会议实体

@Entity(tableName = Meeting.TABLE_NAME)
data class Meeting(
    @PrimaryKey(autoGenerate = true)
    val id: Int?,
    val friendId: Int?,
    val date: LocalDateTime?
) {
    companion object {
        const val TABLE_NAME = "meetings"
    }
}

然后是一个帮助器类来关联它们:

data class FriendMeetings(
    @Embedded
    val friend: Friend= Friend(),
    @Relation(
        parentColumn = "id",
        entityColumn = "friendId"
    )
    val meetings: List<Meeting>
)

还为

LocalDateTime
字段定义了类型转换器

class AppConverters {
    @TypeConverter
    fun fromLocalDateTime(date: LocalDateTime?): Long? =
        date?.toMillis()

    @TypeConverter
    fun toLocalDateTime(millisSinceEpoch: Long?): LocalDateTime? =
        if (millisSinceEpoch == null) {
            null
        } else LocalDateTime.ofInstant(
            Instant.ofEpochMilli(millisSinceEpoch),
            ZoneId.systemDefault()
        )
}

当我在 dao 中询问所有朋友的列表时,它的效果非常好

@Query("SELECT * FROM friends ORDER BY id")
fun getAll(): List<FriendMeetings>

如果我在 dao 中要求在给定的日期与朋友会面,它会很有效

@Query("SELECT * FROM friends INNER JOIN meetings ON friends.id = meetings.friendId WHERE friends.id = :id AND meetings.date BETWEEN :startOfDay AND :endOfDay")
fun getMeetingsWithFriendBetweenDates(id: Long, startOfDay: Long, endOfDay: Long): FriendMeetings?

但是如果我尝试在给定日期举行所有会议,结果将不正确

@Query("SELECT * FROM friends INNER JOIN meetings ON friends.id = meetings.friendId WHERE meetings.date BETWEEN :startOfDay AND :endOfDay")
fun getMeetingsBetweenDates(startOfDay: Long, endOfDay: Long): List<FriendMeetings>?

在这种情况下,我得到了正确的朋友数量,但在会议正确的情况下,朋友数据会一直重复。我只是想,由于一天的会议不会很多,我可以加载会议,然后为每个会议加载朋友,但似乎有点令人讨厌,但我不知道这里出了什么问题

android sqlite android-room android-room-relation
1个回答
0
投票

当 Room 对 @Relation 执行操作时,它将以任意顺序返回相应父级的所有子级。也就是说

@Query
仅用于确定父级,底层
@Relations
是由不带参数的底层查询构建的。

您需要做的是绕过/覆盖 Room 的便利处理。这可以通过使用具有控制两个因素的主体的函数来实现:-

  1. 找回父母,以及
  2. 找回孩子们

所以我相信您对所有

Friend
但在提供的开始和结束日期之间有
Meeting
的解决方案可能是在
@Dao
接口或抽象类中具有以下功能:-

@Query("SELECT * FROM friends ORDER BY id")
fun getAllFriends(): List<Friend>
@Query("SELECT * FROM meetings WHERE meetings.friendId=:friendId AND meetings.date BETWEEN :startOfDay: Long AND :endOfDay")
fun getMeetingsForAFriendBetweenDates(friendId: Int?, startOfDay: Long, endOfDay: Long): List<Meeting>

@Transaction
@Query("")
fun getFriendWithMeetingsBetweenDates(id: Long, startOfDay: Long, endOfDay: Long): List<FriendMeetings> {
    val rv = ArrayList<FriendMeetings>()
    for(f in getAllFriends()) {
        val meetings = getMeetingsForAFriendBetweenDates(f.id, startOfDay, endOfDay)
        rv.add(FriendMeetings(f,meetings))
    }
    return rv
}
  • @Query("")
    是让Room将
    @Transaction
    应用到函数
© www.soinside.com 2019 - 2024. All rights reserved.