如何使用 asscociateBy table 从 @Embedded 关系中仅获取不同的值?

How to get only distinct values from an @Embedded relationship using asscociateBy table?

是否可以使用 @Embedded 和 asscociatedBy = Junction() 生成仅包含不同对象(来自子实体)的列表table?

我有几个通过链接关联的独立实体(EntityActivityLog、EntityComponent、EntityGroup)table (EntityLinkGroupToActivity)。

本质上,每个ActivityLog 都有多个组件,而这些组件又有多个组。 (它继续但为了这个问题的目的我会停在那里)

目前我正在使用如下简化的数据集:

[activityLog1, component1,group1]

[activity日志 1、组件 1、组 2]

[activityLog1, component1,group3]

[activity日志 1、组件 2、组 1]

[activityLog1, component4,group1]

[activity日志 2,组件 1,组 1] 等...

使用以下代码,我期望一个包含单个嵌入式 activity 对象和唯一组件实体列表的 pojo。每个 componentId 将与链接 table.

中的 activityLogId 相关联
data class ActivityLogWithComponentList (
    @Embedded
    val activityLog: EntityLogActivity,
    @Relation(
        parentColumn = "activityLogId",
        entity = EntityComponent::class,
        entityColumn = "componentId ",
        associateBy = Junction(
            EntityLinkGroupToActivity::class,
            parentColumn = "activityLogId",
            entityColumn = "componentId ",
        )
    )
    val componentList: List<EntityComponent>
){}

但是,在第一个 activityLog 的结果中有 9x 个组件。

POJO 列表结果:

组件 1、组件 1、组件 1、组件 2、组件 4...

我可以理解包含所有 componentId 的链接 table 的 'junction' 的逻辑,组件实体 table 也是如此。因此,结点的每一行总是被满足。然而,这不是我正在寻找的结果,也没有看到 associateBy = junction() 的替代方法。

理想情况下,我只针对列表中不同的组件项目:component1、component2、component4

任何关于如何使用这种嵌入式方法实现这一目标的建议都将不胜感激。

补充说明:

编码 DISTINCT 对 @Relation 没有影响,room 所做的是构建 运行 它自己的子查询以获取父项的 ALL 个子项。

但是,通过一些额外的 Dao 可以实现:-

前 2 个查询(您可能已经有第一个):-

@Query("SELECT * FROM entityactivitylog")
    abstract fun getAllActivityLogs(): List<EntityActivityLog>
    @Query("SELECT DISTINCT entitycomponent.* " + /*<<<<< ONLY NEED TO GET COMPONENT columns */
            "FROM entitylinkgrouptoactivity " +
            "JOIN entitycomponent ON entitycomponent.componentId = entitylinkgrouptoactivity.componentId " +
            "WHERE activityLogId=:activityLogId")
    abstract fun getDistinctComponentsForAnActivity(activityLogId: Long): List<EntityComponent>
  • 第二个,可以看出,将通过 link table 获得不同的组件(DISTINCT 的替代方法是 GROUP BY 子句,它可能更有用)

然后是一个函数(注意抽象 class 已经被用于 Dao 的,因为可以使用一个带有主体的函数)。此函数伪装成允许@Transaction 注释的查询,它是:-

@Query("")
@Transaction
fun getDistinct(): List<ActivityLogWithComponentList> {
    val rv: ArrayList<ActivityLogWithComponentList> = ArrayList()
    val currentActivityLog: EntityActivityLog
    for (a in getAllActivityLogs()) {
        rv.add(
            ActivityLogWithComponentList(
                activityLog = a,
                componentList = getDistinctComponentsForAnActivity(a.activityLogId!!)
            )
        )
    }
    return rv
}

为了方便和简洁,在主线程上使用上面的内容和(运行):-

const val TAG = "DBINFO"
class MainActivity : AppCompatActivity() {
    lateinit var db: TheDatabase
    lateinit var dao: AllDao
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        db = TheDatabase.getInstance(this)
        dao = db.getAllDao()

        val g1ID = dao.insert(EntityGroup(groupName = "Group1"))
        val g2ID = dao.insert(EntityGroup(groupName = "Group2"))
        val g3ID = dao.insert(EntityGroup(groupName = "Group3"))
        val c1ID = dao.insert(EntityComponent(componentName = "Component1"))
        val c2ID = dao.insert(EntityComponent(componentName = "Component2"))
        val c3ID = dao.insert(EntityComponent(componentName = "Component3"))
        val c4ID = dao.insert(EntityComponent(componentName = "Component4"))
        val a1ID = dao.insert(EntityActivityLog(activityName = "Activity1"))
        val a2ID = dao.insert(EntityActivityLog(activityName = "Activity2"))

        dao.insert(EntityLinkGroupToActivity(activityLogId = a1ID, componentId = c1ID, groupId =  g1ID))
        dao.insert(EntityLinkGroupToActivity(activityLogId = a1ID, componentId = c1ID, groupId = g2ID))
        dao.insert(EntityLinkGroupToActivity(activityLogId = a1ID, componentId = c1ID, groupId = g3ID))
        dao.insert(EntityLinkGroupToActivity(activityLogId = a1ID, componentId = c2ID, groupId = g1ID))
        dao.insert(EntityLinkGroupToActivity(activityLogId = a1ID, componentId = c4ID, groupId = g1ID))
        dao.insert(EntityLinkGroupToActivity(activityLogId = a2ID, componentId = c1ID, groupId = g1ID))

        for(al: ActivityLogWithComponentList in dao.getOriginal()) {
            Log.d(TAG+"RUN1","Activity Log is ${al.activityLog.activityName} it has ${al.componentList.size} components")
            for (c: EntityComponent in al.componentList) {
                Log.d(TAG,"\tComponent is ${c.componentName}")
            }
        }

        for (al: ActivityLogWithComponentList in dao.getDistinct()) {
            Log.d(TAG+"RUN2","Activity Log is ${al.activityLog.activityName} it has ${al.componentList.size} components")
            for (c: EntityComponent in al.componentList) {
                Log.d(TAG,"\tComponent is ${c.componentName}")
            }
        }
    }
}

日志中的结果是:-

原创

2021-12-13 20:13:43.949 D/DBINFORUN1: Activity Log is Activity1 it has 5 components
2021-12-13 20:13:43.949 D/DBINFO:   Component is Component1
2021-12-13 20:13:43.949 I/chatty: uid=10145(a.a.so70330069kotlinroomrelationships) identical 1 line
2021-12-13 20:13:43.949 D/DBINFO:   Component is Component1
2021-12-13 20:13:43.949 D/DBINFO:   Component is Component2
2021-12-13 20:13:43.949 D/DBINFO:   Component is Component4
2021-12-13 20:13:43.949 D/DBINFORUN1: Activity Log is Activity2 it has 1 components
2021-12-13 20:13:43.949 D/DBINFO:   Component is Component1

Distinct/Unique

2021-12-13 20:13:43.961 D/DBINFORUN2: Activity Log is Activity1 it has 3 components
2021-12-13 20:13:43.961 D/DBINFO:   Component is Component1
2021-12-13 20:13:43.961 D/DBINFO:   Component is Component2
2021-12-13 20:13:43.961 D/DBINFO:   Component is Component4
2021-12-13 20:13:43.961 D/DBINFORUN2: Activity Log is Activity2 it has 1 components
2021-12-13 20:13:43.961 D/DBINFO:   Component is Component1