Как я могу представить отношение многих к многим с Android Room?

Как я могу представить отношение многих к многим с комнатой? например, у меня есть «Гость» и «Бронирование». В резервировании может быть много гостей, а гость может быть частью многих резерваций.

Вот мои определения сущностей:

@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 ) 

Изучая документы, я наткнулся на @Relation . Однако я все-таки смутил.

В соответствии с этим я хотел бы создать POJO и добавить туда отношения. Итак, с моим примером я сделал следующее

 data class ReservationForGuest( @Embedded val reservation: Reservation, @Relation( parentColumn = "reservation.id", entityColumn = "id", entity = Guest::class ) val guestList: List<Guest> ) 

Свыше я получаю ошибку компилятора:

Не могу понять, как читать это поле из курсора.

Я не смог найти рабочий образец @Relation .

У меня была аналогичная проблема. Вот мое решение.

Вы можете использовать дополнительный объект ( 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 ) 

Вы можете получить оговорки со своим списком guestId s. (Не гостевые объекты)

 data class ReservationWithGuests( @Embedded val reservation:Reservation, @Relation( parentColumn = "id", entityColumn = "reservationId", entity = ReservationGuest::class, projection = "guestId" ) val guestIdList: List<Long> ) 

Вы также можете получить гостей с их списком reservationId . (Не объекты резервирования)

 data class GuestWithReservations( @Embedded val guest:Guest, @Relation( parentColumn = "id", entityColumn = "guestId", entity = ReservationGuest::class, projection = "reservationId" ) val reservationIdList: List<Long> ) 

Поскольку вы можете получить guestId и reservationId , вы можете запросить объекты Reservation и Guest с ними.

Я обновлю свой ответ, если найду простой способ получить список объектов резервирования и гостевого объекта вместо своих идентификаторов.

Похожие ответы

Исходя из приведенного выше ответа: https://stackoverflow.com/a/44428451/4992598, только сохраняя отдельные имена полей между объектами, вы можете вернуть модели (а не только идентификаторы). Все, что вам нужно сделать, это:

 @Entity data class ReservationGuest( @PrimaryKey(autoGenerate = true) val id: Long, val reservationId: Long, @Embedded val guest: Guest ) 

И да объекты могут быть встроены друг в друга, если вы не сохраняете повторяющиеся поля. Таким образом, класс ReservationWithGuests может выглядеть следующим образом.

 data class ReservationWithGuests( @Embedded val reservation:Reservation, @Relation( parentColumn = "id", entityColumn = "reservationId", entity = ReservationGuest::class, projection = "guestId" ) val guestList: List<Guest> ) 

Таким образом, на этом этапе вы можете использовать val guestIdList: List, потому что ваш объект ReservationGuest фактически отображает идентификаторы с моделями сущностей.

Ниже приведен способ запроса полной объектной модели через таблицу соединений 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 ) 

Дао (обратите внимание, что мы втягиваем M: N через подзапрос и уменьшаем лишние строки Reservation с помощью 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(); 

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(",")); } }