将具有较少字段的新POJO类映射到现有的Room表中

问题描述 投票:4回答:7

当前,我们有以下Dao和model类。

NoteDao

@Query("SELECT * FROM note")
public abstract LiveData<List<Note>> getAllNotes();

Note类

@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();
android sqlite android-sqlite android-room android-database
7个回答
2
投票

"Returning subsets of columns"文档中可以看到:

大多数时候,您需要获取仅实体的几个字段。例如,您的UI可能仅显示用户的名字和姓氏,而不是有关用户的每个详细信息。通过仅提取出现在应用程序UI中的列,可以节省宝贵的资源,并且查询可以更快地完成。

Room允许您从查询中返回任何基于Java的对象,只要可以将结果列集映射到返回的对象中即可。例如,您可以创建以下简单的基于Java的旧对象(PO​​JO),以获取用户的名字和姓氏:

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_namelast_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();

5
投票

这将为您工作:

@Query("SELECT title FROM note") 
LiveData<List<String>> getAllNoteTitles();

当您调用SELECT *时,它将选择表中的所有字段。


0
投票

即使不选择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存储库以获取大致相似的示例应用程序,这将在演示中进行演示)。


0
投票

[如果您仅在课程中添加标题,则会议室将不会加载正文我使用了以下依赖项

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;
    }
}

0
投票

您可以直接使用

@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();
}

只要您的列名相同,即标题


0
投票

您也可以使用可以扩展的@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语句。但是,不能对视图运行INSERTUPDATEDELETE语句。

@Database(entities = {Note.class}, views = {SimpleNote.class}, version = 3)

0
投票

您可以从房间选择查询功能返回任何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);
© www.soinside.com 2019 - 2024. All rights reserved.