#android #android-sqlite #android-room
#Android #android-sqlite #android-room
Вопрос:
У меня есть объект User и объект Record. Я хочу получить список, в котором отображаются все пользователи и их список записей, отфильтрованный по дате записи. Тем не менее, я застрял в том, что не смог отфильтровать результат с помощью условий.
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
Ответ №1:
Давайте посмотрим, как @Relation
это работает. Есть два этапа:
- Room выполняет запрос, который вы ввели,
@Query
чтобы привлечь пользователей. Как обычно, этот запрос не включает никаких объединений. Этот запрос используется для получения той части данных, которые сохраняются в основной таблице (User
в вашем случае). - Room выполняет еще один запрос. Для этого он просматривает
@Relation
параметры и понимает, к какой таблице он должен запросить следующий запрос (Record
в вашем случае) и каким должно быть условие соединения с результатом пользователя. Важно, чтобы у вас не было возможности вмешиваться в этот процесс создания запросов. Например, вы не можете установить фильтр поRecord
полям. Получение результата Room преобразует его в необходимый формат (заполняет списокRecords
).
У вас есть выбор:
- Чтобы изменить отношение, установите фильтры в
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);
@Relation
Чтобы вообще не использовать, напишите запрос с объединениями, подобными тому, который вы пробовали. Но затем вы должны вручную преобразовать результат в нужную форму в коде (результат цикла и формирование списка).