Android Room:无需额外表/自定义查询,用@Relation关联多@Embedded实体类?
Room中实现A与X-Y配对关联的无额外表方案
首先明确:Room的@Relation注解原生不支持直接关联包含多个@Embedded实体的组合类(比如你定义的XWithY),因为@Relation的设计逻辑是单实体与父实体的关联,无法直接处理跨两个表的配对关联——这和你猜测的限制一致。
如果不想新增额外表,也尽量减少自定义查询,可以基于现有的AWithXY关联表(三元关联表,主键为A、X、Y的外键组合),通过嵌套@Relation的方式实现需求,具体步骤如下:
1. 确保关联表实体定义正确
假设你的AWithXY关联表实体是这样的(明确三元主键):
@Entity(primaryKeys = [AWithXY.FK_A, AWithXY.FK_X, AWithXY.FK_Y]) data class AWithXY( val FK_A: Long, val FK_X: Long, val FK_Y: Long )
2. 定义中间关联类
先创建一个关联类,用来绑定AWithXY与对应的X、Y实体:
data class XYJunctionWithEntities( @Embedded val junction: AWithXY, @Relation( parentColumn = AWithXY.FK_X, entityColumn = BaseColumns.PK, entity = X::class ) val x: X, @Relation( parentColumn = AWithXY.FK_Y, entityColumn = BaseColumns.PK, entity = Y::class ) val y: Y )
3. 定义A与XY配对的最终数据类
通过嵌套@Relation,让A关联所有对应的XYJunctionWithEntities:
data class AWithXYPairs( @Embedded val a: A, @Relation( parentColumn = BaseColumns.PK, entityColumn = AWithXY.FK_A, entity = AWithXY::class ) val xyPairs: List<XYJunctionWithEntities> )
4. DAO层查询
使用@Transaction确保查询的原子性,配合简单的查询语句即可:
@Dao interface ADao { @Transaction @Query("SELECT * FROM A") fun getAllAWithXYPairs(): List<AWithXYPairs> }
5. 业务层转换(可选)
如果需要直接得到List<XWithY>,可以在业务层做简单转换:
val aWithPairs = dao.getAllAWithXYPairs() val xYPairList = aWithPairs.flatMap { it.xyPairs.map { pair -> XWithY(pair.x, pair.y) } }
关键说明
- 这种方案完全不需要新增表,仅利用现有的关联表和Room原生的
@Embedded、@Relation、@Transaction能力实现; - 不需要编写复杂的JOIN自定义查询,仅用基础的
SELECT *即可; - 无法完全避免自定义查询(DAO必须定义查询方法),但这是Room数据访问的必要环节,不属于复杂的关联查询范畴。
内容的提问来源于stack exchange,提问作者Luke
相关产品推荐
相关产品推荐

