当前,我们有以下Dao和model类。
@Query("SELECT * FROM note")
public abstract LiveData<List<Note>> getAllNotes();
@Entity(
tableName = "note"
)
public class Note {
@ColumnInfo(name = "title")
private String title;
// Can contain a huge String.
@ColumnInfo(name = "body")
private String body;
}
但是,在某些情况下,我们只希望仅加载title
。
一次加载带有大Note
字符串的所有body
,可能会导致OutOfMemoryException
有没有办法,我们可以如下创建另一个POJO?
public class SimpleNote {
private String title;
}
然后,我们能够从SimpleNote
返回NoteDao
的列表吗?
@Query("???")
public abstract LiveData<List<SimpleNote>> getAllSimpleNotes();
在"Returning subsets of columns"文档中可以看到:
大多数时候,您需要获取仅实体的几个字段。例如,您的UI可能仅显示用户的名字和姓氏,而不是有关用户的每个详细信息。通过仅提取出现在应用程序UI中的列,可以节省宝贵的资源,并且查询可以更快地完成。
Room允许您从查询中返回任何基于Java的对象,只要可以将结果列集映射到返回的对象中即可。例如,您可以创建以下简单的基于Java的旧对象(POJO),以获取用户的名字和姓氏:
data class NameTuple(
@ColumnInfo(name = "first_name") val firstName: String?,
@ColumnInfo(name = "last_name") val lastName: String?
)
现在,您可以在查询方法中使用此POJO:
@Dao
interface MyDao {
@Query("SELECT first_name, last_name FROM user")
fun loadFullName(): List<NameTuple>
}
Room理解查询返回
first_name
和last_name
列的值,并且这些值可以映射到NameTuple
类的字段中。因此,Room可以生成正确的代码。如果查询返回的列过多,或NameTuple
类中不存在列,则Room显示警告。
回到您的情况:已经这样定义SimpleNote
:
public class SimpleNote {
@ColumnInfo(name = "title")
private String title;
}
然后您可以查询表:
@Query("SELECT title FROM note")
public abstract LiveData<List<SimpleNote>> getAllSimpleNotes();
这将为您工作:
@Query("SELECT title FROM note")
LiveData<List<String>> getAllNoteTitles();
当您调用SELECT *
时,它将选择表中的所有字段。
即使不选择String
列,也可以将其映射为Note
,而不使用类型:
body
在房间里,@Query("SELECT title FROM note")
LiveData<List<Note>> getAllNotesPreview();
通常与@Entity
1:1映射到一个表。因此,不可能将两个对象自动映射到同一张表。实际上,按列名进行选择似乎是最少的工作,仅从那里读取时这没问题。对于读/写访问,仍然需要记录的完整详细视图,其中包含所有列。
尽管提供的代码看起来像Java,但在Kotlin中,它也可能是:
ORM
这将排除突变,当不是所有的列都已被查询和映射时,这才有意义。否则,例如,可能仅将不存在的@Query("SELECT title FROM note")
Flow<List<Note>> getAllNotesPreview();
列空白。编辑body
列。请参阅title
(CodeLab)或Using Flow with Room(请参见相关的GitHub存储库以获取大致相似的示例应用程序,这将在演示中进行演示)。
[如果您仅在课程中添加标题,则会议室将不会加载正文我使用了以下依赖项
Unidirectional data flow on Android using Kotlin
我创建的SimpleNote类如下
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
implementation 'androidx.lifecycle:lifecycle-common-java8:2.2.0'
implementation 'androidx.room:room-runtime:2.2.4'
annotationProcessor 'androidx.room:room-compiler:2.2.4'
我只能按以下方式查询标题
public class SimpleNote {
private String title;
public SimpleNote(String title) {
this.title = title;
}
public String getTitle() {
return title;
}
}
您可以直接使用
@Dao
public interface NotesDao {
@Query("SELECT * FROM notes_table")
LiveData<List<Notes>> loadAllNotes();
@Insert
void insertNotes(List<Notes> notes);
//loads only the title
@Query("SELECT * FROM notes_table")
LiveData<List<SimpleNote>> loadSimpleNotes();
}
只要您的列名相同,即标题
您也可以使用可以扩展的@Query("SELECT title FROM note")
public abstract LiveData<List<SimpleNote>> getAllSimpleNotes();
public class SimpleNote {
private String title;
}
。
view into the database
您只需要在数据库实体中注册它。
@DatabaseView(value = "SELECT title FROM note", viewName = "simple-note")
public class SimpleNote {
@ColumnInfo(name = "title")
private String title;
}
注:像实体一样,您可以对视图运行SELECT语句。但是,不能对视图运行INSERT,UPDATE或DELETE语句。
@Database(entities = {Note.class}, views = {SimpleNote.class}, version = 3)
您可以从房间选择查询功能返回任何POJO,只需要在查询字符串上坚持POJO的字段名。
@Query("SELECT * from simple-note")
public abstract LiveData<List<SimpleNote>> getAllSimpleNotes();
如果您的查询返回了POJo的所有必填字段,那么您就很好了。这是灵活性的示例:
class SumAveragePojo
{
public float total;
public float average;
}
所以您可以放心地做:
@Query("SELECT SUM(stepCount) as total, AVG(stepCount) as average FROM userFitnessDailyRecords where forDay BETWEEN :startDay AND :endDay ORDER BY forDay ASC")
SumAveragePojo getUserFitnessSumAndAverageForLastThirtyDays(Date startDay, Date endDay);