Определите отношения один-ко-многим между сущностями комнаты для модели чата - PullRequest
8 голосов
/ 15 февраля 2020

Я начал использовать базу данных Room и просмотрел несколько документов для создания объектов Room. Это мои отношения. Канал чата может иметь много разговоров. Так что это идет как отношения один ко многим. Поэтому я создал сущности, как показано ниже.

Канальная сущность

@Entity(primaryKeys = ["channelId"])
@TypeConverters(TypeConverters::class)
data class Channel(
    @field:SerializedName("channelId")
    val channelId: String,
    @field:SerializedName("channelName")
    val channelName: String,
    @field:SerializedName("createdBy")
    val creationTs: String,
    @field:SerializedName("creationTs")
    val createdBy: String,
    @field:SerializedName("members")
    val members: List<String>,
    @field:SerializedName("favMembers")
    val favMembers: List<String>
) {
  // Does not show up in the response but set in post processing.
  var isOneToOneChat: Boolean = false
  var isChatBot: Boolean = false
}

Диалоговая сущность

@Entity(primaryKeys = ["msgId"],
    foreignKeys = [
        ForeignKey(entity = Channel::class,
                parentColumns = arrayOf("channelId"),
                childColumns = arrayOf("msgId"),
                onUpdate = CASCADE,
                onDelete = CASCADE
        )
    ])
@TypeConverters(TypeConverters::class)
data class Conversation(

    @field:SerializedName("msgId")
    val msgId: String,
    @field:SerializedName("employeeID")
    val employeeID: String,
    @field:SerializedName("channelId")
    val channelId: String,
    @field:SerializedName("channelName")
    val channelName: String,
    @field:SerializedName("sender")
    val sender: String,
    @field:SerializedName("sentAt")
    val sentAt: String,
    @field:SerializedName("senderName")
    val senderName: String,
    @field:SerializedName("status")
    val status: String,
    @field:SerializedName("msgType")
    val msgType: String,
    @field:SerializedName("type")
    val panicType: String?,
    @field:SerializedName("message")
    val message: List<Message>,
    @field:SerializedName("deliveredTo")
    val delivered: List<Delivered>?,
    @field:SerializedName("readBy")
    val read: List<Read>?

) {

data class Message(
        @field:SerializedName("txt")
        val txt: String,
        @field:SerializedName("lang")
        val lang: String,
        @field:SerializedName("trans")
        val trans: String
)

data class Delivered(
        @field:SerializedName("employeeID")
        val employeeID: String,
        @field:SerializedName("date")
        val date: String
)

data class Read(
        @field:SerializedName("employeeID")
        val employeeID: String,
        @field:SerializedName("date")
        val date: String
)

    // Does not show up in the response but set in post processing.
    var isHeaderView: Boolean = false
}

Теперь, когда вы можно увидеть Диалог принадлежит Каналу . Когда пользователь видит список каналов, мне нужно отобразить несколько атрибутов last Conversation в элементе списка. У меня вопрос, достаточно ли этого, если я просто объявлю отношение, как указано выше, или я должен содержать объект Converstion в классе Channel? Каковы другие способы, которыми я могу справиться с этим? Поскольку пользовательскому интерфейсу необходимо получать последние разговоры, которые произошли вместе со временем, status et c. в каждом элементе списка каналов, когда пользователь прокручивает. Так что не должно быть никаких задержек в пользовательском интерфейсе из-за этого, когда я запрашиваю.

И как я могу иметь недавний объект Converstaion в объекте Channel?

Ответы [ 2 ]

1 голос
/ 21 февраля 2020

Я предлагаю создать другой класс (не в БД, просто для показа в пользовательском интерфейсе), например:

data class LastConversationInChannel(
    val channelId: String,
    val channelName: String,
    val creationTs: String,
    val createdBy: String,
    val msgId: String,
    val employeeID: String,
    val sender: String,
    val sentAt: String,
    val senderName: String
    .
    .
    .
)

Получить последний разговор в каждом канале по этому запросу:

 SELECT Channel.*
 ,IFNULL(LastConversation.msgId,'') msgId
 ,IFNULL(LastConversation.sender,'') sender
 ,IFNULL(LastConversation.employeeID,'') employeeID
 ,IFNULL(LastConversation.sentAt,'') sentAt
 ,IFNULL(LastConversation.senderName,'') senderName
 from Channel left join 
 (SELECT * from Conversation a  
 WHERE a.msgId IN ( SELECT b.msgId  FROM Conversation AS b 
                    WHERE a.channelId = b.channelId 
                    ORDER BY b.sentAt DESC  LIMIT 1 )) as LastConversation
 on Channel.channelId = LastConversation.channelId

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

 @Query(" SELECT Channel.*\n" +
            " ,IFNULL(LastConversation.msgId,'') msgId\n" +
            " ,IFNULL(LastConversation.sender,'') sender\n" +
            " ,IFNULL(LastConversation.employeeID,'') employeeID\n" +
            " ,IFNULL(LastConversation.sentAt,'') sentAt\n" +
            " ,IFNULL(LastConversation.senderName,'') senderName\n" +
            " from Channel left join \n" +
            " (SELECT * from Conversation a  \n" +
            " WHERE a.msgId IN ( SELECT b.msgId  FROM Conversation AS b \n" +
            "                    WHERE a.channelId = b.channelId \n" +
            "                    ORDER BY b.sentAt DESC  LIMIT 1 )) as LastConversation\n" +
            " on Channel.channelId = LastConversation.channelId")
    fun getLastConversationInChannel(): LiveData<List<LastConversationInChannel>>

Достаточно ли этого, если я просто объявлю отношение, как указано выше, или я должен содержать объект Converstion в классе Channel?

Вы не должны содержать Conversation в классе Channel, потому что Room создаст для него несколько столбцов в таблице Conversation.

0 голосов
/ 26 февраля 2020

Вы можете иметь LastConversation, который является Conversation object внутри Шанель. Вы должны обновлять это каждый раз, когда обновляется lastConversation, изменяя таблицу Chanel из слоя Room. (Не так много производительности для обновления базы данных). Путем осуществления сортировки для списка Chanel (Comparable). Ваше обновление пользовательского интерфейса будет круто. И ваша логика c из пользовательского интерфейса или ViewModel проще. Я тоже так делал.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...