Как объединить несколько экземпляров одного и того же объекта в Android Комната? - PullRequest
5 голосов
/ 23 апреля 2020

ПРИМЕЧАНИЕ. Я не могу использовать отношение, поскольку у нас возникла проблема с производительностью, которая не воспроизводится при запросе прямого соединения.

Пока я не добавил target user и group user и соответствующие

LEFT JOIN chat_user ON chat_user.chat_user_id = message_item.messages_target_user
LEFT JOIN chat_user ON chat_user.chat_user_id = message_item.messages_from_group_user

Это сработало хорошо. Но после добавления я не могу понять, как заставить эти префиксы отображаться в запросе.

class ReadMessageEntity(
  @Embedded
  var message: MessageEntity,
  @Embedded
  var block: BlockEntity?,
  @Embedded
  var user: ChatUserRelationEntity,
  @Embedded(prefix = "target_user_")
  var targetUser: ChatUserEntity?,
  @Embedded(prefix = "from_group_user_")
  var fromGroupUser: ChatUserEntity?
)

Это то, что я пытаюсь запросить:

  @Transaction
  @Query("""
    SELECT * FROM message_item 
    LEFT JOIN block_item ON block_item.block_message_id = message_item.message_local_id
    LEFT JOIN chat_user_relation ON chat_user_relation.chat_user_id = message_item.message_user_id
    LEFT JOIN chat_user ON chat_user.chat_user_id = message_item.messages_target_user
    LEFT JOIN chat_user ON chat_user.chat_user_id = message_item.messages_from_group_user
    WHERE message_item.message_chat_id = :chatId
    ORDER BY message_created_at ASC
    """)
  fun getMessagesByChat(chatId: String): Single<List<ReadMessageEntity>>

Ошибка:

e: ошибка: возникла проблема с запросом: [SQLITE_ERROR] SQL ошибка или отсутствует база данных (неоднозначное имя столбца: main.chat_user.chat_user_id)

Ответы [ 3 ]

1 голос
/ 26 апреля 2020

как уже упоминалось Moayad. AlMoghrabi Я должен использовать псевдонимы таблицы. Поэтому я переименовал LEFT JOIN chat_user в LEFT JOIN chat_user target_user. Обратите внимание, что между пользователем-чатом и target_user нет AS. (моя ошибка состояла в том, что я попытался поместить это там). Поведение префиксов до сих пор остается для меня загадкой, так как префикс для chat_user работает правильно, но если я добавлю префикс к ChatUserRelationEntity, то получу неизвестную ошибку столбца.

SELECT * FROM message_item 
LEFT JOIN block_item
    ON block_item.block_message_id = message_item.message_local_id
LEFT JOIN chat_user_relation 
    ON chat_user_relation.chat_user_relation_chat_user_id = message_item.message_user_id
    AND chat_user_relation.chat_user_relation_chat_user_chat_id = :chatId
LEFT JOIN chat_user target_user 
    ON target_user.chat_user_id = message_item.messages_target_user
LEFT JOIN chat_user from_group_user 
    ON from_group_user.chat_user_id = message_item.messages_from_group_user
WHERE message_item.message_chat_id = :chatId
ORDER BY message_created_at ASC
1 голос
/ 26 апреля 2020

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

РЕДАКТИРОВАТЬ:

Я нашел что-то похожее на вашу проблему: https://github.com/JetBrains/Exposed/issues/177

Также они ссылались на этот код в качестве примера, чтобы исправить это выпуск:

    object Users : Table() {
        val id = varchar("id", 10).primaryKey()
        val name = varchar("name", length = 50)
        val residentialCityId = optReference("resid_city_id", Cities)
        val bornCityId = optReference("born_city_id", Cities)
    }

    object Cities : IntIdTable() {
        val name = varchar("name", 50) // Column
    }
    fun test() {
        val userTable1 = Users.alias("u1")
        val userTable2 = Users.alias("u2")

        Cities
            .innerJoin(userTable1, {Cities.id}, {userTable1[Users.residentialCityId]})
            .innerJoin(userTable2, {Cities.id}, {userTable2[Users.bornCityId]})
            .selectAll()
    }
0 голосов
/ 26 апреля 2020

Вот мое решение для соединения:

ChatsEntity

@Entity(tableName = "Chats",foreignKeys = [ForeignKey(entity = UserEntity::class,
parentColumns = ["id"], childColumns = ["userId"], onDelete = NO_ACTION),ForeignKey(entity = LastMessageEntity::class,
parentColumns = ["id"], childColumns = ["roomId"], onDelete = NO_ACTION)])
data class ChatsEntity(
  @PrimaryKey(autoGenerate = true)
  var id: Int? = null,
  @ColumnInfo(name = "roomId") var roomId: String,
  @ColumnInfo(name = "userId") var userId: String,
  @ColumnInfo(name = "count") var count: Int
)

LastMessageEntity

@Entity(tableName = "LastMessages")
data class LastMessageEntity(
   @PrimaryKey @ColumnInfo(name = "id") var id: String = "",
   @ColumnInfo(name = "message") var message: String = "",
   @ColumnInfo(name = "type") var type: String = ""
)

UserEntity

@Entity(tableName = "Users")
data class UserEntity(
   @PrimaryKey @ColumnInfo(name = "id") var id: String = "",
   @ColumnInfo(name = "username") var username: String = "",
   @ColumnInfo(name = "token") var token: String = ""
)

1. используя соотношение

class ChatUserMessage {
@Embedded
var chat : ChatsEntity? = null

@Relation(parentColumn = "userId", entityColumn = "id")
var user : UserEntity? = null

@Relation(parentColumn = "roomId", entityColumn = "id")
var lastMessage : LastMessageEntity? = null

}

SQL Запрос

@Query("SELECT * FROM Chats")
fun getAllChats(): List<ChatUserMessage?>?

2. без использования отношения

class ChatUserMessage
{
  @Embedded
  var chat: ChatsEntity? = null

  @Embedded(prefix = "user_")
  var user:  UserEntity? = null

  @Embedded(prefix = "message_")
  var lastMessage: LastMessageEntity? = null
}

Запрос

@Query("SELECT Chats.*, LastMessages.id as  message_id,LastMessages.message as  message_message, LastMessages.type as  message_type, Users.id as user_id, Users.username as user_username, Users.token as user_token FROM Chats INNER JOIN LastMessages ON LastMessages.id = Chats.roomId INNER JOIN Users ON Users.id = Chats.userId")
fun getAllChats(): List<ChatUserMessage?>?
...