Android Room Many to Many Junction 表获得超过 2 个表的关系

标签 android sqlite many-to-many android-room junction-table

我在 User、Property 和这两项 UserPropertyJunction 的联结表之间创建了一个关系,可以将其可视化为下图中的关系
enter image description here
用户实体,而不是 customers ,即

@Entity(tableName = "user")
data class UserEntity(
    @PrimaryKey
    val userId: Long,
    val firstName: String,
    val lastName: String,
    val email: String,
    val password: String
)
属性,而不是 products ,
@Entity(
    tableName = "property",
    primaryKeys = ["id"]
)
data class Property(
    val id: Int,
    val update: Int,
    val categoryId: Int,
    val title: String,
    val subject: String,
    val type: String,
    val typeId: Int
}
和连接表而不是 product_helper
@Entity(
    tableName = "user_property_junction",
    primaryKeys = ["userAccountId", "propertyId"],
    // Foreign Keys
    foreignKeys = [
        ForeignKey(
            entity = User::class,
            parentColumns = ["userId"],
            childColumns = ["userAccountId"],
            onDelete = ForeignKey.NO_ACTION
        ),
        ForeignKey(
            entity = Property::class,
            parentColumns = ["id"],
            childColumns = ["propertyId"],
            onDelete = ForeignKey.NO_ACTION
        )
    ]
)
data class UserPropertyJunction(
    val userAccountId: Long,
    val propertyId: Int
)
并创建了关系类
data class UserWithFavorites(

    @Embedded
    val user: User,

    @Relation(
        parentColumn = "userId",
        entity = Property::class,
        entityColumn = "id",
        associateBy = Junction(
            value = UserPropertyJunction::class,
            parentColumn = "userAccountId",
            entityColumn = "propertyId"
        )
    )
    val propertyList: List<Property>
)
还需要获取用户显示和喜欢这些属性的次数的数据。
为此,请查看解决方案 in this link它将附加字段添加到连接,在我的情况下添加 displayCountfavorite特性
data class UserPropertyJunction(
    val userAccountId: Long,
    val propertyId: Int,
    val displayCount:Int=0,
    val favorite:Boolean=false
)
我的第一个问题是据我所见,对联结表或关联表没有太多经验,它们只存储应该关联的表的外键,是否可以将值字段添加到联结表?
如果它不优雅或不是首选的方式,我应该添加另一个与联结表有关系的表,例如
data class PropertyStatus(
    val userAccountId: Long,
    val propertyId: Int,
    val displayCount:Int=0,
    val favorite:Boolean=false
)
并将它们联系起来?
当从用户的属性和属性的状态检索数据时,我应该手动从
data class UserWithProperties(

    @Embedded
    val user: User,

    @Relation(
        parentColumn = "userId",
        entity = Property::class,
        entityColumn = "id",
        associateBy = Junction(
            value = UserPropertyJunction::class,
            parentColumn = "userAccountId",
            entityColumn = "propertyId"
        )
    )
    val propertyList: List<Property>
)
并根据您对第一个问题的回答从状态表或联结表中获取 SELECT
或者是否可以将另一个关系添加到 UserWithProperties@Embedded@Relation

最佳答案

据我所知,不幸的是,没有开箱即用的方法,您如何仅使用 Room 的工具(@Relation、@Embedded、@Junction)来解决您的用例。

My first question is as far as i have seen, not much experience with junction or associative tables, they only store foreign keys for the tables that should associate with, is it okay to add value fields to junction table?


问题是@Junction 在使用上有一些限制——它只是有助于将两个表与保存在第三个(联结)表中的值绑定(bind)。但是@Relation-with-@Junction API不支持从此联结表中获取要包含到结果类的任何字段(这些外键仅用于绑定(bind))。这就是为什么从技术上讲,您可以将一些字段添加到联结表(它似乎是您应该保留这些值的最合适的位置),但实际上您无法使用 @Junction 获取这些字段。
也许你可以使用一些hack-ish方式,但我猜 - 你必须用SQL连接实现你自己的方法并通过循环传递结果以形成所需的结果(类似于你提到的链接中实现的在你的帖子中)。
为简化 对于您的情况,您可以真正按照您的建议描述 Entity-junction 表(但根本不使用 @Junction):
data class UserPropertyJunction(
    val userAccountId: Long,
    val propertyId: Int,
    val displayCount:Int=0,
    val favorite:Boolean=false
)
然后添加辅助类(不是实体)并将其用作查询结果:
data class UserWithFavorites(
    val displayCount:Int,
    val favorite:Boolean,
    @Relation(
         parentColumn = "userAccountId",
         entityColumn = "userId"
    )
    val user: UserEntity,
    @Relation(
         parentColumn = "propertyId",
         entityColumn = "id"
    )
    val property: Property,
)
当然,这不是你想要的,但至少你可以处理它,它是开箱即用的,你可以使用 LiveData/Flow/RxJava(例如,在得到这个之后,你可以尝试使用一些转换运营商以某种方式将其更改为所需的格式)
更新(简化版)
如果您在结果中不需要用户,但您只想按 userId 过滤,那么您的辅助类可能如下:
data class PropertiesWithFavorites(
    val displayCount:Int,
    val favourite:Boolean,
    val propertyId: Long,
    @Relation(
         parentColumn = "propertyId",
         entityColumn = "id"
    )
    val property: Property
)
和道法:
@Query("SELECT * FROM user_property_junction as j where j.userAccountId =:userId")
fun getPropertiesByUser(userId: Long): List<PropertiesWithFavorites>  

关于Android Room Many to Many Junction 表获得超过 2 个表的关系,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63887061/

相关文章:

php - 使用 php 通过 android volley 发送图像

Android gradle 在合并时更改资源

将逗号分隔列拆分为多对多关系的 SQL 查询

java - 无列名 - 创建后

sql - 使用 join 更新多行速度非常慢

php - Laravel 5.5 更新多对多关系模型的复选框

python - Django:删除关系末尾时未触发 m2m_changed

android - 如何在android中实现这种按钮结构

android - webview.loadUrl ("about:blank") 问题

android - HTC Desire HD 的 Sqlite 问题