首页 > 解决方案 > 如何将条件应用于关系,或者如何正确处理 Room 中带有 WHERE 子句的 JOIN 查询?

问题描述

请耐心等待,我对架构组件和一般的 android 都是新手。我的问题与这个问题类似,但不幸的是,接受的答案似乎不起作用。我在 这个答案中有一个一对多关系的例子。我的示例数据库有两个表 USERS 和 PETS,如下图所示:

12

假设我想获取一个用户列表,其中包含按用户 ID 分组的宠物列表,只有小于 5 岁的宠物。结果应该如下所示(伪代码):

{uId:2,[Pet3,Pet4];uId:4,[宠物6,宠物7];}

另一个要求是 Dao 需要将列表作为 LiveData 对象返回,因为我使用的是 MVVM 架构并希望它能够感知生命周期和可观察。

有了这些要求,UserDao将如下所示:

@Dao
interface UserDao {

    @Insert
    void insert(User user);

    @Transaction
    @Query("SELECT USERS.uId, PETS.pId , PETS.userId, PETS.age " + 
    "FROM USERS INNER JOIN PETS ON PETS.userId = USERS.uId " +
    "WHERE PETS.age < 5 " +
    "GROUP BY USERS.uId")
    LiveData<List<UserWithPets>> getUserPets();

}

用户实体:

@Entity
public class User {
    @PrimaryKey
    public int id; // User id
}

宠物实体:

@Entity
public class Pet {
    @PrimaryKey
    public int id;     // Pet id
    public int userId; // User id
    public int age;
}

现在的问题是:我应该如何设计房间可以理解的 UserWithPets 并按照我想要的方式映射光标?这是我到目前为止所尝试的:

方法一:

在我看来,最方便的方法是使用关系,就像下面的 POJO 一样。

UserWithPets POJO:

public class UserWithPets {
    @Embedded
    public User user;

    @Relation(parentColumn = "id", entityColumn = "userId", entity = Pet.class)
    public List<Pet> pets; 

}

不幸的是,谷歌尚未实现将条件分配给关系的功能。因此,对于拥有 5 岁以下宠物的每个用户,我们总是会获得完整的宠物列表。希望这将很快成为可能,因为功能请求已经分配在这里这里

谷歌在功能请求中的声明:“我们计划实施一些查询重写逻辑来解决这些问题,不是针对 2.1,但希望在 2.2 中我们将更多地关注关系。”

方法二:

另一种选择是同时嵌入用户和宠物,例如:

public class UserWithPets {
    @Embedded
    public User user;

    @Embedded
    public Pet pet;

}

这也不起作用,因为现在我们每个用户只能得到 1 只宠物。

方法3:

这个答案建议只创建一个从用户扩展的合并类,例如:

public class UserWithPets extends User {

    @Embedded(prefix = "PETS_")
    List<Pet> pets = new ArrayList<>();
}

我尝试了很多方式,无论有没有构造器,但我无法让它工作。它总是给出错误,例如“实体和 Pojos 必须有一个可用的公共构造函数。你可以有一个空的构造函数或一个参数与字段匹配的构造函数(按名称和类型)。-java.util.List”或查询返回一些列... UserWithPets 不使用。所以这里欢迎任何建议。

方法4:

只需进行两个查询并将结果拼接在一起。我将如何使用 LiveData 做到这一点?加入操作应该在哪里进行?我不能在活动中做到这一点,这不是 MVVM 模式的重点。而且不在存储库或视图模型中,因为 LiveData 是不可变的。还是有其他方法?

获得上述要求的结果的可行解决方案是什么?

标签: androidandroid-roompojorelationandroid-livedata

解决方案


推荐阅读