Как получить полный объект entity с комнатой запросов, используя таблицу с FK

#java #android #sql #kotlin #android-room

#java #Android #sql #kotlin #android-комната

Вопрос:

Допустим, у меня есть эти таблицы :

Таблица — пользователь

Хранит пользователей

 @Entity(
    tableName = "USER"
)
data class User(
    @PrimaryKey(autoGenerate = true)
    @ColumnInfo(name = "user_id")
    val id: Int,

    @ColumnInfo(name = "user_name")
    val name: String
)
  

Таблица — элемент

Храните элементы, которые похожи на продукт

 @Entity(
    tableName = "ITEM"
)
data class Item(
    @PrimaryKey(autoGenerate = true)
    @ColumnInfo(name = "item_id")
    val id: Int,

    @ColumnInfo(name = "item_name")
    val name: String,

    @ColumnInfo(name = "item_description")
    val description: String
)

  

Таблица — специальная

Сохраните специальность для продукта 1 Для существования специального продукта требуется

 @Entity(
    tableName = "SPECIAL",
    foreignKeys = [ForeignKey(
        entity = Item::class,
        parentColumns = ["item_id"],
        childColumns = ["special_item_id"]
    )]
)
data class Special(
    @PrimaryKey(autoGenerate = true)
    @ColumnInfo(name = "special_id")
    val id: Int,

    @ColumnInfo(name = "special_item_id")
    val coupon_product_id: Int,

    @ColumnInfo(name = "special_name")
    val name: String,

    @ColumnInfo(name = "special_description")
    val description: String

)

  

Таблица — Избранное

Хранит избранные специальные предложения от пользователя

 @Entity(
    tableName = "TB_FAVOURITE",
    foreignKeys = [ForeignKey(
        entity = User::class,
        parentColumns = ["user_id"],
        childColumns = ["favourite_user_id"]
    ), ForeignKey(
        entity = Special::class,
        parentColumns = ["special_id"],
        childColumns = ["favourite_special_id"]
    )]
)
data class Favourite(
    @PrimaryKey
    @ColumnInfo(name = "favourite_user_id")
    val id: Int,

    @ColumnInfo(name = "favourite_special_id")
    val specialId: Int

)
  

Мой вопрос в том, как я могу сделать запрос, чтобы выбрать все специальные предложения, а затем создать подобный класс, который хранит, нравится ли он пользователю или нет. На данный момент это одно пользовательское приложение, оно для демонстрационного приложения. Таким образом, user всегда будет одним и тем же, поэтому я могу жестко закодировать findById и отправить идентификатор пользователя.

Цель

Заключается в получении результата запроса в виде списка, который содержит :

  1. Все специальные
  2. В SomeClass должен содержаться элемент специального inside
  3. Флаг, позволяющий узнать, является ли он предпочтительным для этого драйвера или нет

Дело в том, что я хочу иметь возможность сопоставлять результат базы данных room с моим желаемым объектом, поэтому я предполагаю, что запрос важнее, чем mapper, я знаю, как выполнить mapper.

Обратите внимание, что я использую assets/database/mydb.db файл для запуска базы данных, я не знаю, имеет ли это значение.

Каким должен быть запрос для этого? Есть ли какое-либо улучшение структуры базы данных, чтобы упростить ее?

Комментарии:

1. взгляните на Embedded . При ее использовании вы определяете соединения с отношением

2. @Stachu не могли бы вы добавить пример в качестве ответа?

Ответ №1:

вы могли бы создать класс, подобный этому:

 class SpecialWithFavourite {
    @Embedded
    var special: Special? = null
    @Relation(parentColumn = "special_item_id", entityColumn = "item_id")
    var item: Item? = null
    @Relation(parentColumn = "special_id", entityColumn = "favourite_special_id")
    var favourite: Favourite? = null
}
  

а затем извлечь его с помощью dao query следующим образом:

 @Dao
interface DaoSpecialWithFavourite {
    @Transaction
    @Query("SELECT SPECIAL.* FROM SPECIAL INNER JOIN TB_FAVOURITE WHERE TB_FAVOURITE.favourite_user_id = :userId")
    fun getLD(userId: Long): List<SpecialWithFavourite>
}
  

другим вариантом является использование представления, особенно если вам нужны только поля fiew

 @DatabaseView("SELECT SPECIAL.*, ITEM.item_name FROM SPECIAL INNER JOIN ITEM ON ITEM.item_id = SPECIAL.special_item_id")
class FavSpecial {
    var name: String? = null
    @Embedded
    var special: Special? = null
}
  

согласно обсуждению в комментариях, новый Favourite

 data class Favourite(
    @PrimaryKey(autoGenerate = true)
    val id: Int,
    @ColumnInfo(name = "favourite_user_id")
    val userid: Int,
    @ColumnInfo(name = "favourite_special_id")
    val specialId: Int
)
  

таким образом, вы по-прежнему сохраняете ограничения, и у пользователя может быть несколько избранных специальных предложений

Комментарии:

1. У меня возникают проблемы при попытке вставить, сбой (android.database.sqlite. Исключение SQLiteConstraintException: сбой УНИКАЛЬНОГО ограничения: TB_FAVOURITE.favorite_user_id (код 1555 SQLITE_CONSTRAINT_PRIMARYKEY))

2. Я неправильно создал таблицу FAVORITE? с этим первичным ключом?

3. для FAVOURITE первичного ключа есть favourite_user_id , который ограничен USER.user_id , поэтому у вас может быть только один на пользователя. Так ли это задумано? Я бы создал отдельный ключ для этой таблицы, особенно тот, который позволит пользователю иметь несколько избранных

4. Нет, я хочу быть таблицей, в которой я могу найти, например, пользователя, которого 1 имеет в качестве избранного 2, 3, 4, поэтому первый столбец — user_id, который может быть любым user_id базы данных, а избранным должен быть special_id.

5. Но мне нужно добавить туда PK… так что я не знаю, должны ли оба быть PK или что. но может быть, что существует более одного другого идентификатора пользователя.