Ben*_*fez 15 sqlite android android-room
让我们举个例子:我有一个表单,其中有几个部分,每个部分都有问题.侧面,我有答案映射到问题,他们有另一列,我想在查询时过滤:
所以我有以下实体:
@Entity(tableName = "sections")
public class Section {
@PrimaryKey
public long id;
public String title;
}
@Entity(tableName = "questions")
public class Question {
@PrimaryKey
public long id;
public String title;
public long sectionId;
}
@Entity(tableName = "answers")
public class Answer {
@PrimaryKey
public long id;
public long questionId;
public int otherColumn;
}
Run Code Online (Sandbox Code Playgroud)
在DAO部分,我想要检索所有这些.
这是我想通过此查询填充的POJO:
class SectionWithQuestions {
@Embedded
public Section section;
@Relation(parentColumn = "id", entityColumn = "sectionId", entity = Question.class)
public List<QuestionWithAnswer> questions;
public static class QuestionWithAnswer {
@Embedded
public Question question;
@Relation(parentColumn = "id", entityColumn = "questionId", entity = Answer.class)
List<Answer> answers;
}
}
Run Code Online (Sandbox Code Playgroud)
在另一个应用程序中,查询将是:
SELECT s.*, q.*, a.*
FROM sections s
LEFT JOIN questions q ON q.sectionId = s.id
LEFT JOIN answers a ON a.questionId = q.id
WHERE s.id = :sectionId and a.otherColumn = :otherColumn
Run Code Online (Sandbox Code Playgroud)
但是在Room中我发现如果你想要一个对象及其关系(如示例中的用户及其宠物),则只选择该对象,并在第二个查询中查询关系.那将是:
@Query("SELECT * FROM sections WHERE id = :sectionId")
Run Code Online (Sandbox Code Playgroud)
然后在生成的代码中会有(伪代码):
sql = "SELECT * FROM sections WHERE id = :sectionId" // what's inside @Query
cursor = query(sql)
int indexColumn1 = cursor.getColumnIndex(col1)
int indexColumn2
... etc
while (cursor.moveToNext) {
masterObject = new object()
masterObject.property1 = cursor.get(indexColumn1)
... etc
__fetchRelationshipXXXAsYYY(masterObject.relations) // fetch the child objects
}
Run Code Online (Sandbox Code Playgroud)
这个__fetch XXX as YYY方法如下:
sql = "SELECT field1, field2, ... FROM a WHERE foreignId IN (...)"
similar algo as previously: fetch column indices, and loop through the cursor
Run Code Online (Sandbox Code Playgroud)
所以基本上它创建了2个查询:一个用于主对象,一个用于关系.第二个查询是自动创建的,我们无法控制它.
为了回到我想要关系的问题,但也过滤了子列,我陷入困境:
otherColumn列,因为它不存在@Relation我不能,因为这个注释的唯一属性是连接列和实体定义这可能在房间里,还是我必须自己制作子查询?
奖金问题:为什么他们不在一个查询中连接表,而是创建2个查询?这是出于性能原因吗?
编辑以澄清我的期望:
这就是我期望写的:
@Query("SELECT s.*, q.*, a.* " +
"FROM sections s " +
"LEFT JOIN questions q ON q.sectionId = s.id " +
"LEFT JOIN answers a ON a.questionId = q.id " +
"WHERE s.id = :sectionId and a.otherColumn = :additionalIntegerFilter")
SectionWithQuestionsAndAnswers fetchFullSectionData(long sectionId);
static class SectionWithQuestionsAndAnswers {
@Embedded Section section;
@Relation(parentColumn = "id", entityColumn = "sectionId", entity = Question.class)
List<QuestionWithAnswers> questions;
}
static class QuestionWithAnswers {
@Embedded Question question;
@Relation(parentColumn = "id", entityColumn = "questionId", entity = Answer.class)
Answer answer; // I already know that @Relation expects List<> or Set<> which is
// not useful if I know I have zero or one relation (ensured
// through unique keys)
}
Run Code Online (Sandbox Code Playgroud)
这是我想象由Room实现的伪代码作为生成的代码:
function fetchFullSectionData(long sectionId, long additionalIntegerFilter) {
query = prepare(sql); // from @Query
query.bindLong("sectionId", sectionId);
query.bindLong("additionalIntegerFilter", additionalIntegerFilter);
cursor = query.execute();
Section section = null;
long prevQuestionId = 0;
Question question = null;
while (cursor.hasNext()) {
if (section == null) {
section = new Section();
section.questions = new ArrayList<>();
section.field1 = cursor.get(col1); // etc for all fields
}
if (prevQuestionId != cursor.get(questionIdColId)) {
if (question != null) {
section.questions.add(question);
}
question = new Question();
question.fiedl1 = cursor.get(col1); // etc for all fields
prevQuestionId = question.id;
}
if (cursor.get(answerIdColId) != null) { // has answer
Answer answer = new Answer();
answer.field1 = cursor.get(col1); // etc for all fields
question.answer = answer;
}
}
if (section !=null && question != null) {
section.questions.add(question);
}
return section;
}
Run Code Online (Sandbox Code Playgroud)
这是一个查询,我的所有对象都被提取.
我只是粘贴我发布的功能请求中提供的信息(请参阅我对问题的评论):
您好 - 我们最近发布了一项新功能,可以使用 Multimap 返回类型定义关系查询方法。有了这个新功能,您应该能够实现本线程中讨论的结果。有关此新功能的更多信息,您可以查看以下资源:
- 定义对象之间的关系:https ://developer.android.com/training/data-storage/room/relationships
- ADS 2021 中的关系查询方法:https://youtu.be/i5coKoVy1g4 ?t=344
- 新的 MapInfo 注释:https ://developer.android.com/reference/androidx/room/MapInfo
我知道仅链接的答案并不好,但我没有机会对此进行测试。如果有人有更好的答案,我会接受。
| 归档时间: |
|
| 查看次数: |
1555 次 |
| 最近记录: |