Сопоставить новый класс POJO с меньшими полями с существующей таблицей номеров - PullRequest
4 голосов
/ 23 февраля 2020

В настоящее время у нас есть следующий класс Dao и модель.

NoteDao

@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 s с большой body строкой сразу, может вызвать OutOfMemoryException

Есть ли способ, которым мы можем создать еще один POJO следующим образом?

public class SimpleNote {
    private String title;
}

Затем мы можем вернуть список SimpleNote из NoteDao?

@Query("???")
public abstract LiveData<List<SimpleNote>> getAllSimpleNotes();

Ответы [ 7 ]

5 голосов
/ 27 февраля 2020

Это будет работать для вас:

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

Когда вы звоните SELECT *, он выберет все поля внутри таблицы.

2 голосов
/ 27 февраля 2020

Как видно из «Возвращение подмножеств столбцов» документы:

В большинстве случаев вам нужно получить только несколько полей сущности . Например, ваш пользовательский интерфейс может отображать только имя и фамилию пользователя, а не каждую информацию о пользователе. Выбирая только столбцы, которые появляются в пользовательском интерфейсе вашего приложения, вы сохраняете ценные ресурсы, и ваш запрос выполняется быстрее.

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, Комната отображает предупреждение.


Назад к вашему делу : определив SimpleNote как таковой:

public class SimpleNote {
    @ColumnInfo(name = "title")
    private String title;
}

Затем вы можете запросить таблицу:

@Query("SELECT title FROM note")
public abstract LiveData<List<SimpleNote>> getAllSimpleNotes();
0 голосов
/ 02 марта 2020

Вы можете вернуть любой POJO из функции запроса выбора комнаты, вам просто нужно придерживаться имен полей вашего POJO в строке запроса.

class SumAveragePojo
{ 
    public float total;
    public float average;
}

Если ваш запрос возвращает все необходимые поля для вашего POJo тогда вы хороши для go. Вот пример гибкости этого:

@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();
0 голосов
/ 29 февраля 2020

Вы можете использовать представление в базе данных , которое также будет расширяемым.

@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)

Примечание: Подобно сущностям, вы можете запускать операторы SELECT для представлений. Однако вы не можете запускать операторы INSERT , UPDATE или DELETE для представлений.

@Query("SELECT * from simple-note")
public abstract LiveData<List<SimpleNote>> getAllSimpleNotes();
0 голосов
/ 27 февраля 2020

вы можете напрямую использовать

@Query("SELECT title FROM note")
public abstract LiveData<List<SimpleNote>> getAllSimpleNotes();


public class SimpleNote {
    private String title;
}

, если имя вашего столбца одинаковое, т.е.

0 голосов
/ 27 февраля 2020

Если вы только добавили заголовок в классе, Комната не будет загружать тело, я использовал следующие зависимости

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, который я создал, выглядит следующим образом

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();
}
0 голосов
/ 27 февраля 2020

Вместо использования типа String его можно сопоставить с Note, даже если не выбран столбец body:

@Query("SELECT title FROM note")
LiveData<List<Note>> getAllNotesPreview();

В комнате @Entity обычно отображается 1 : 1 к таблице, как обычно для ORM . Поэтому автоматическое сопоставление двух объектов в одной таблице невозможно. Выбор по имени столбца (столбцам) действительно кажется наименьшим усилием, что не составляет проблемы, если только читать оттуда. Для доступа на чтение / запись все равно потребуется полный подробный просмотр записи, в которой есть все столбцы.


Несмотря на то, что представленный код выглядит как Java, в Kotlin это может также быть:

@Query("SELECT title FROM note")
Flow<List<Note>> getAllNotesPreview();

Это исключит мутацию, которая имеет смысл, когда не все столбцы были запрошены и отображены. В противном случае он может только очистить отсутствующий столбец body, например, если. редактирование столбца title. См. Использование Flow with Room (CodeLab) или Однонаправленный поток данных на Android с использованием Kotlin (см. Связанный репозиторий GitHub для примерно аналогичного примера приложения, который демонстрирует это) .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...