如何过滤与 android room db 的一对多关系
How to filter in one to many relationship with android room db
我有一个用户实体和一个记录实体。我想获得一个列表,显示所有用户及其按记录日期过滤的记录列表。但是,我无法根据条件过滤结果。
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
让我们看看 @Relation
是如何工作的。分为两个阶段:
- Room 执行您在
@Query
中输入的查询以获取用户。像往常一样,该查询不包含任何连接。此查询用于获取主table(在您的情况下为User
)中保留的那部分数据。
- 房间再执行一项查询。为此,它会查看
@Relation
参数并了解接下来应该查询的 table 内容(在您的情况下为 Record
)以及用户结果应该 join-condition 的内容。重要的是您无法侵入此 query-making 进程。例如,您不能在 Record
的字段上设置过滤器。获取结果 Room 将其转换为所需的格式(填充 Records
的列表)。
您有以下选择:
- 要在
Records
table 上设置过滤器来扭转关系(但这样你会得到没有列表的平面数据)。
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);
- 根本不要使用
@Relation
,像您尝试过的那样使用联接编写查询。但是你应该在代码中手动将结果转换为所需的形式(循环结果并形成列表)。
我有一个用户实体和一个记录实体。我想获得一个列表,显示所有用户及其按记录日期过滤的记录列表。但是,我无法根据条件过滤结果。
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
让我们看看 @Relation
是如何工作的。分为两个阶段:
- Room 执行您在
@Query
中输入的查询以获取用户。像往常一样,该查询不包含任何连接。此查询用于获取主table(在您的情况下为User
)中保留的那部分数据。 - 房间再执行一项查询。为此,它会查看
@Relation
参数并了解接下来应该查询的 table 内容(在您的情况下为Record
)以及用户结果应该 join-condition 的内容。重要的是您无法侵入此 query-making 进程。例如,您不能在Record
的字段上设置过滤器。获取结果 Room 将其转换为所需的格式(填充Records
的列表)。
您有以下选择:
- 要在
Records
table 上设置过滤器来扭转关系(但这样你会得到没有列表的平面数据)。
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);
- 根本不要使用
@Relation
,像您尝试过的那样使用联接编写查询。但是你应该在代码中手动将结果转换为所需的形式(循环结果并形成列表)。