如何将条件应用于关系,或者如何在 Room 中正确处理带有 WHERE 子句的 JOIN 查询?

svo*_*oid 5 android pojo relation android-room android-livedata

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

12

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

{uId:2,[Pet3,Pet4];uId: 4, [Pet6, Pet7];}

另一个要求是 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();

}
Run Code Online (Sandbox Code Playgroud)

用户实体:

@Entity
public class User {
    @PrimaryKey
    public int id; // User id
}
Run Code Online (Sandbox Code Playgroud)

宠物实体:

@Entity
public class Pet {
    @PrimaryKey
    public int id;     // Pet id
    public int userId; // User id
    public int age;
}
Run Code Online (Sandbox Code Playgroud)

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

方法一:

我认为最方便的方法是使用关系,如下面的 POJO 所示。

UserWithPets POJO:

public class UserWithPets {
    @Embedded
    public User user;

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

}
Run Code Online (Sandbox Code Playgroud)

不幸的是,谷歌尚未实现为关系分配条件的功能。因此,我们总是会为每个拥有 5 岁以下宠物的用户提供完整的宠物列表。希望这很快就能实现,因为功能请求已在此处此处分配。

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

方法二:

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

public class UserWithPets {
    @Embedded
    public User user;

    @Embedded
    public Pet pet;

}
Run Code Online (Sandbox Code Playgroud)

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

方法三:

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

public class UserWithPets extends User {

    @Embedded(prefix = "PETS_")
    List<Pet> pets = new ArrayList<>();
}
Run Code Online (Sandbox Code Playgroud)

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

方法四:

只需进行两个查询并将结果拼接在一起即可。我该如何使用 LiveData 来做到这一点?加盟操作应该在哪里进行呢?我无法在 Activity 中执行此操作,这不是 MVVM 模式的重点。并且不在存储库或视图模型中,因为 LiveData 是不可变的。或者还有别的办法吗?

获得满足上述要求的结果的有效解决方案是什么?