bon*_*ond 43 android kotlin android-room android-architecture-components
我怎样才能代表与房间的多对多关系?例如,我有"访客"和"预订".预订可以有很多客人,客人可以参加许多预订.
这是我的实体定义:
@Entity data class Reservation(
@PrimaryKey val id: Long,
val table: String,
val guests: List<Guest>
)
@Entity data class Guest(
@PrimaryKey val id: Long,
val name: String,
val email: String
)
Run Code Online (Sandbox Code Playgroud)
在调查我遇到的文档时@Relation.我发现它真的很混乱.
根据这个,我想创建一个POJO并在那里添加关系.所以,以我的例子,我做了以下
data class ReservationForGuest(
@Embedded val reservation: Reservation,
@Relation(
parentColumn = "reservation.id",
entityColumn = "id",
entity = Guest::class
) val guestList: List<Guest>
)
Run Code Online (Sandbox Code Playgroud)
上面我得到编译器错误:
无法弄清楚如何从游标中读取此字段.
我无法找到工作样本@Relation.
Dev*_*rim 71
我有类似的问题.这是我的解决方案.
您可以使用一个额外的实体(ReservationGuest),它保留之间的关系Guest和Reservation.
@Entity data class Guest(
@PrimaryKey val id: Long,
val name: String,
val email: String
)
@Entity data class Reservation(
@PrimaryKey val id: Long,
val table: String
)
@Entity data class ReservationGuest(
@PrimaryKey(autoGenerate = true) val id: Long,
val reservationId: Long,
val guestId: Long
)
Run Code Online (Sandbox Code Playgroud)
您可以使用他们的guestIds 列表进行预订.(不是客人对象)
data class ReservationWithGuests(
@Embedded val reservation:Reservation,
@Relation(
parentColumn = "id",
entityColumn = "reservationId",
entity = ReservationGuest::class,
projection = "guestId"
) val guestIdList: List<Long>
)
Run Code Online (Sandbox Code Playgroud)
您还可以获取客人的reservationIds 列表.(不是预订对象)
data class GuestWithReservations(
@Embedded val guest:Guest,
@Relation(
parentColumn = "id",
entityColumn = "guestId",
entity = ReservationGuest::class,
projection = "reservationId"
) val reservationIdList: List<Long>
)
Run Code Online (Sandbox Code Playgroud)
既然你可以得到guestIds和reservationIds,你就可以查询Reservation和Guest实体.
如果我找到一种简单的方法来获取Reservation和Guest对象列表而不是它们的id,我会更新我的答案.
Nis*_*hal 42
通过介绍Junction in room,您可以轻松处理多对多关系。
正如@Devrim 所说,您可以使用一个额外的实体 (ReservationGuest) 来保持 Guest 和 Reservation 之间的关系(也称为关联表或连接表或连接表)。
@Entity
data class Guest(
@PrimaryKey
val gId: Long,
val name: String,
val email: String
)
@Entity
data class Reservation(
@PrimaryKey
val rId: Long,
val table: String
)
@Entity(
primaryKeys = ["reservationId", "guestId"]
)
data class ReservationGuest(
val reservationId: Long,
val guestId: Long
)
Run Code Online (Sandbox Code Playgroud)
现在您可以使用此模型向客人预订:
data class ReservationWithGuests (
@Embedded
val reservation: Reservation,
@Relation(
parentColumn = "rId",
entity = Guest::class,
entityColumn = "gId",
associateBy = Junction(
value = ReservationGuest::class,
parentColumn = "reservationId",
entityColumn = "guestId"
)
)
val guests: List<Guest>
)
Run Code Online (Sandbox Code Playgroud)
您还可以让客人获得他们的预订清单。
data class GuestWithReservations (
@Embedded
val guest: Guest,
@Relation(
parentColumn = "gId",
entity = Reservation::class,
entityColumn = "rId",
associateBy = Junction(
value = ReservationGuest::class,
parentColumn = "guestId",
entityColumn = "reservationId"
)
)
val reservations: List<Reservation>
)
Run Code Online (Sandbox Code Playgroud)
现在您可以查询数据库的结果为:
@Dao
interface GuestReservationDao {
@Query("SELECT * FROM Reservation")
fun getReservationWithGuests(): LiveData<List<ReservationWithGuests>>
@Query("SELECT * FROM Guest")
fun getGuestWithReservations(): LiveData<List<GuestWithReservations>>
}
Run Code Online (Sandbox Code Playgroud)
Nom*_*sta 10
实际上,还有另一种获取Guest列表的可能性,不仅是@Devrim答案中的id 。
先定义类将代表之间的连接Guest和Reservation。
@Entity(primaryKeys = ["reservationId", "guestId"],
foreignKeys = [
ForeignKey(entity = Reservation::class,
parentColumns = ["id"],
childColumns = ["reservationId"]),
ForeignKey(entity = Guest::class,
parentColumns = ["id"],
childColumns = ["guestId"])
])
data class ReservationGuestJoin(
val reservationId: Long,
val guestId: Long
)
Run Code Online (Sandbox Code Playgroud)
每次插入new时Reservation,都必须插入ReservationGuestJoinobject才能满足外键约束。现在,如果要获取Guest列表,则可以使用SQL查询的功能:
@Dao
interface ReservationGuestJoinDao {
@SuppressWarnings(RoomWarnings.CURSOR_MISMATCH)
@Query("""
SELECT * FROM guest INNER JOIN reservationGuestJoin ON
guest.id = reservationGuestJoin.guestId WHERE
reservationGuestJoin.reservationId = :reservationId
""")
fun getGuestsWithReservationId(reservationId: Long): List<Guest>
}
Run Code Online (Sandbox Code Playgroud)
要查看更多详细信息,请访问此博客。
这是一种通过单个查询中的M:N联结表查询完整对象模型的方法.子查询可能不是最有效的方法,但它确实有效,直到他们@Relation正确地完成ForeignKey. 我将Guest/Reservation框架手动插入到我的工作代码中,因此可能存在拼写错误.
实体(已涵盖)
@Entity data class Guest(
@PrimaryKey val id: Long,
val name: String,
val email: String
)
@Entity data class Reservation(
@PrimaryKey val id: Long,
val table: String
)
@Entity data class ReservationGuest(
@PrimaryKey(autoGenerate = true) val id: Long,
val reservationId: Long,
val guestId: Long
)
Run Code Online (Sandbox Code Playgroud)
Dao(注意我们通过子查询拉入M:N并Reservation用a 减少额外的行GROUP_CONCAT
@Query("SELECT *, " +
"(SELECT GROUP_CONCAT(table) " +
"FROM ReservationGuest " +
"JOIN Reservation " +
"ON Reservation.id = ReservationGuest.reservationId " +
"WHERE ReservationGuest.guestId = Guest.id) AS tables, " +
"FROM guest")
abstract LiveData<List<GuestResult>> getGuests();
Run Code Online (Sandbox Code Playgroud)
GuestResult(它处理查询结果的映射,请注意我们将连接的字符串转换回列表@TypeConverter)
@TypeConverters({ReservationResult.class})
public class GuestResult extends Guest {
public List<String> tables;
@TypeConverter
public List<String> fromGroupConcat(String reservations) {
return Arrays.asList(reservations.split(","));
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
17520 次 |
| 最近记录: |