将具有较少字段的新 POJO class 映射到现有房间 table
Map new POJO class with lesser fields to an existing Room table
目前,我们有以下 Dao 和模型 class。
NoteDao
@Query("SELECT * FROM note")
public abstract LiveData<List<Note>> getAllNotes();
备注class
@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;
}
然后,我们可以从 NoteDao
?
return 列表 SimpleNote
@Query("???")
public abstract LiveData<List<SimpleNote>> getAllSimpleNotes();
这对你有用:
@Query("SELECT title FROM note")
LiveData<List<String>> getAllNoteTitles();
当您调用 SELECT *
时,它将 select table.
中的所有字段
即使不选择 body
列,也可以将其映射到 Note
,而不是使用类型 String
:
@Query("SELECT title FROM note")
LiveData<List<Note>> getAllNotesPreview();
在 Room 中,@Entity
通常被映射 1:1 到 table,因为 ORM 很常见。因此,将两个对象自动映射到同一个 table 是不可能的。按列名选择确实似乎是最省力的,仅从那里读取时没有问题。对于 read/write 访问,仍然需要记录的完整详细信息视图,其中包含所有列。
尽管提供的代码看起来很像 Java,但在 Kotlin 中也可能是:
@Query("SELECT title FROM note")
Flow<List<Note>> getAllNotesPreview();
这将排除突变,这在并非所有列都已被查询和映射时才有意义。否则它可能只会空白缺席的 body
列,例如。编辑 title
列。请参阅 Using Flow with Room (CodeLab) or Unidirectional data flow on Android using Kotlin(请参阅相关的 GitHub 存储库以获取大致相似的示例应用程序,该示例应用程序正在对其进行演示)。
如果您只在 class 中添加标题,房间将不会加载 body
我使用了以下依赖项
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'
而我创建的SimpleNote class如下
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();
}
如 "Returning subsets of columns" 文档中所示:
Most of the time, you need to get only a few fields of an entity. For example, your UI might display just a user's first name and last name, rather than every detail about the user. By fetching only the columns that appear in your app's UI, you save valuable resources, and your query completes more quickly.
Room allows you to return any Java-based object from your queries as long as the set of result columns can be mapped into the returned object. For example, you can create the following plain old Java-based object (POJO) to fetch the user's first name and last name:
data class NameTuple(
@ColumnInfo(name = "first_name") val firstName: String?,
@ColumnInfo(name = "last_name") val lastName: String?
)
Now, you can use this POJO in your query method:
@Dao
interface MyDao {
@Query("SELECT first_name, last_name FROM user")
fun loadFullName(): List<NameTuple>
}
Room understands that the query returns values for the first_name
and last_name
columns and that these values can be mapped into the fields of the NameTuple
class. Therefore, Room can generate the proper code. If the query returns too many columns, or a column that doesn't exist in the NameTuple
class, Room displays a warning.
回到你的案例:已经这样定义了 SimpleNote
:
public class SimpleNote {
@ColumnInfo(name = "title")
private String title;
}
然后可以查询table:
@Query("SELECT title FROM note")
public abstract LiveData<List<SimpleNote>> getAllSimpleNotes();
可以直接使用
@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;
}
您只需要在数据库实体中注册它。
@Database(entities = {Note.class}, views = {SimpleNote.class}, version = 3)
Note: Like entities, you can run SELECT statements against views. However, you cannot run INSERT, UPDATE, or DELETE statements against views.
@Query("SELECT * from simple-note")
public abstract LiveData<List<SimpleNote>> getAllSimpleNotes();
您可以return房间中的任何 POJO select 查询函数,您只需要在查询字符串中坚持使用 POJO 的字段名称即可。
class SumAveragePojo
{
public float total;
public float average;
}
如果您的查询return包含 POJo 的所有必需字段,那么您就可以开始了。这是灵活性的示例:
@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);
所以你可以安全地做:
@Query("SELECT title FROM note")
LiveData<List<SimpleNote>> getAllNoteTitles();
目前,我们有以下 Dao 和模型 class。
NoteDao
@Query("SELECT * FROM note")
public abstract LiveData<List<Note>> getAllNotes();
备注class
@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;
}
然后,我们可以从 NoteDao
?
SimpleNote
@Query("???")
public abstract LiveData<List<SimpleNote>> getAllSimpleNotes();
这对你有用:
@Query("SELECT title FROM note")
LiveData<List<String>> getAllNoteTitles();
当您调用 SELECT *
时,它将 select table.
即使不选择 body
列,也可以将其映射到 Note
,而不是使用类型 String
:
@Query("SELECT title FROM note")
LiveData<List<Note>> getAllNotesPreview();
在 Room 中,@Entity
通常被映射 1:1 到 table,因为 ORM 很常见。因此,将两个对象自动映射到同一个 table 是不可能的。按列名选择确实似乎是最省力的,仅从那里读取时没有问题。对于 read/write 访问,仍然需要记录的完整详细信息视图,其中包含所有列。
尽管提供的代码看起来很像 Java,但在 Kotlin 中也可能是:
@Query("SELECT title FROM note")
Flow<List<Note>> getAllNotesPreview();
这将排除突变,这在并非所有列都已被查询和映射时才有意义。否则它可能只会空白缺席的 body
列,例如。编辑 title
列。请参阅 Using Flow with Room (CodeLab) or Unidirectional data flow on Android using Kotlin(请参阅相关的 GitHub 存储库以获取大致相似的示例应用程序,该示例应用程序正在对其进行演示)。
如果您只在 class 中添加标题,房间将不会加载 body 我使用了以下依赖项
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'
而我创建的SimpleNote class如下
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();
}
如 "Returning subsets of columns" 文档中所示:
Most of the time, you need to get only a few fields of an entity. For example, your UI might display just a user's first name and last name, rather than every detail about the user. By fetching only the columns that appear in your app's UI, you save valuable resources, and your query completes more quickly.
Room allows you to return any Java-based object from your queries as long as the set of result columns can be mapped into the returned object. For example, you can create the following plain old Java-based object (POJO) to fetch the user's first name and last name:
data class NameTuple(
@ColumnInfo(name = "first_name") val firstName: String?,
@ColumnInfo(name = "last_name") val lastName: String?
)
Now, you can use this POJO in your query method:
@Dao
interface MyDao {
@Query("SELECT first_name, last_name FROM user")
fun loadFullName(): List<NameTuple>
}
Room understands that the query returns values for the
first_name
andlast_name
columns and that these values can be mapped into the fields of theNameTuple
class. Therefore, Room can generate the proper code. If the query returns too many columns, or a column that doesn't exist in theNameTuple
class, Room displays a warning.
回到你的案例:已经这样定义了 SimpleNote
:
public class SimpleNote {
@ColumnInfo(name = "title")
private String title;
}
然后可以查询table:
@Query("SELECT title FROM note")
public abstract LiveData<List<SimpleNote>> getAllSimpleNotes();
可以直接使用
@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;
}
您只需要在数据库实体中注册它。
@Database(entities = {Note.class}, views = {SimpleNote.class}, version = 3)
Note: Like entities, you can run SELECT statements against views. However, you cannot run INSERT, UPDATE, or DELETE statements against views.
@Query("SELECT * from simple-note")
public abstract LiveData<List<SimpleNote>> getAllSimpleNotes();
您可以return房间中的任何 POJO select 查询函数,您只需要在查询字符串中坚持使用 POJO 的字段名称即可。
class SumAveragePojo
{
public float total;
public float average;
}
如果您的查询return包含 POJo 的所有必需字段,那么您就可以开始了。这是灵活性的示例:
@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);
所以你可以安全地做:
@Query("SELECT title FROM note")
LiveData<List<SimpleNote>> getAllNoteTitles();