【问题标题】:How to filter in one to many relationship with android room db如何过滤与android room db的一对多关系
【发布时间】:2020-10-14 21:22:58
【问题描述】:

我有一个用户实体和一个记录实体。我想要一个列表,显示所有用户及其按记录日期过滤的记录列表。但是,我无法根据条件过滤结果。

def room_version = "2.2.5"
implementation "androidx.room:room-runtime:$room_version"
@Entity(tableName = "user_table")
public class User {
    @PrimaryKey public long id;
    public String name;
}

@Entity(tableName = "record_table")
public class Record {
    @PrimaryKey @ColumnInfo(name = "record_id")public long recordId;
    @ColumnInfo(name = "user_id") public long userId;
    public String date;
    @ColumnInfo(name = "action")
    public String action;
}

public class UserWithRecords {
    @Embedded
    protected User user;
    @Relation(
            parentColumn = "id",
            entity = Record.class,
            entityColumn = "user_id"
    )
    protected List<Record> records;
}

这是我尝试过的所有查询:

//in Dao  
//first try:
@Transaction
@Query("SELECT * FROM user_table LEFT JOIN record_table ON id = user_id WHERE date=:date")
public LiveData<List<UserWithRecords>> getDailyRecord(String date);

//second try:
@Transaction
@Query("SELECT * FROM user_table LEFT JOIN (SELECT * FROM record_table WHERE date=:date) ON id = user_id")
public LiveData<List<UserWithRecords>> getDailyRecord(String date);

//third try:
@Transaction
@Query("SELECT * FROM user_table INNER JOIN record_table ON id = user_id WHERE date=:date")
public LiveData<List<UserWithRecords>> getDailyRecord(String date);

<User>          <Record>
 id | name     record_id | user_id | action | date
------------   ----------------------------------------
 1  | Alice         1    | 1       | walk   |2020-10-05
 2  | Ben           2    | 1       | jog    |2020-10-05
 3  | Chris         3    | 2       | bike   |2020-10-05
                    4    | 1       | walk   |2020-10-14
                    5    | 2       | jog    |2020-10-14

filtering by 2020-10-05 and get results with all queries:
id | name | record_id | action | date
----------------------------------
 1 | Alice|   1       | walk   | 2020-10-05
 1 | Alice|   2       | jog    | 2020-10-05
 1 | Alice|   4       | walk   | 2020-10-14
 2 | Ben  |   3       | bike   | 2020-10-05
 2 | Ben  |   5       | jog    | 2020-10-14
 3 | Chris|------------------------------------->3rd query don't have this row 

我怎样才能得到这样的东西?是否可以通过一个查询来完成?

id | name | record_id | action | date
-------------------------------------------
 1 | Alice|   1       | walk   | 2020-10-05
 1 | Alice|   2       | jog    | 2020-10-05
 2 | Ben  |   3       | bike   | 2020-10-05   

【问题讨论】:

    标签: android android-sqlite android-room


    【解决方案1】:

    让我们看看@Relation 是如何工作的。有两个阶段:

    1. Room 执行您在@Query 中输入的查询以获取用户。像往常一样,该查询不包括任何联接。此查询用于获取保留在主表中的那部分数据(在您的情况下为User)。
    2. 房间执行了另外一个查询。为此,它查看@Relation 参数并了解接下来应该查询哪个表(在您的情况下为Record)以及用户结果的连接条件应该是什么。重要的是,您无法侵入此查询制作过程。例如,您不能在Record 的字段上设置过滤器。获取结果 Room 将其转换为所需格式(填充 Records 列表)。

    你有选择:

    1. 扭转关系以在Records 表上设置过滤器(但这样您将获得没有列表的平面数据)。
    public class UserWithRecords {
        @Embedded
        protected Record record;
        @Relation(
                parentColumn = "user_id",
                entity = User.class,
                entityColumn = "id"
        )
        protected User user;
    }
    

    并将查询更改为:

    @Transaction
    @Query("SELECT * FROM record_table WHERE date=:date")
    public LiveData<List<UserWithRecords>> getDailyRecord(String date);
    
    1. 根本不使用@Relation,使用您尝试过的联接编写查询。但是您应该在代码中手动将结果转换为所需的形式(循环结果并形成列表)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-11-20
      • 2023-03-12
      • 2020-07-27
      • 1970-01-01
      • 2018-07-04
      相关资源
      最近更新 更多