How to join multiple instances of same object in Android Room?

前端 未结 3 690
北恋
北恋 2020-12-21 01:28

NOTE: I cannot use relation as we had performance issue which is not reproduced on direct join query.

Until I added target user and from group use

相关标签:
3条回答
  • 2020-12-21 01:30

    Here is my join solution:

    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. using relation

    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

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

    2. without using relation

    class ChatUserMessage
    {
      @Embedded
      var chat: ChatsEntity? = null
    
      @Embedded(prefix = "user_")
      var user:  UserEntity? = null
    
      @Embedded(prefix = "message_")
      var lastMessage: LastMessageEntity? = null
    }
    

    Query

    @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?>?
    
    0 讨论(0)
  • 2020-12-21 01:46

    as mentioned Moayad .AlMoghrabi I should use table aliases. So I renamed LEFT JOIN chat_user to LEFT JOIN chat_user target_user. Note there is no AS between chat-user and target_user. (my mistake was that I tried to put it there). Behavior of prefixes is still a mystery to me as the prefix for chat_user works properly, but if I put the prefix to ChatUserRelationEntity then I receive unknown column error.

    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
    
    0 讨论(0)
  • 2020-12-21 01:52

    In the query, you have to set an alias for the table chat_user as you are joining it twice in the same name which will confuse database engine so it tells you that the field is ambiguous.

    EDIT:

    I found something that may be similar to your issue: https://github.com/JetBrains/Exposed/issues/177

    Also they referred to this code as an example to fix this issue:

        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 讨论(0)
提交回复
热议问题