Как стать автором
Обновить

Room: Один ко многим

Время на прочтение3 мин
Количество просмотров20K
Всем привет. На дворе 2018 и уже почти год как Google активно работает над Architecture Components. Неплохая документация и примеры позволяют начать использование новых компонентов без каких-либо проблем и сложностей. Но всегда есть ложка дегтя в бочке меда кода. Заметки ниже не претендуют на истину, но, возможно, сэкономят два-три часа гугления и просмотра кода библиотек.

Один ко многим


Тут все просто: в документации сказано как организовать классы, чтобы получить связь сущностей «один ко многим». Берем 2 сущности:

@Entity
public class DialogPojo {
    @NonNull
    @PrimaryKey
    String id;
//other fields
}
@Entity(
        foreignKeys = @ForeignKey(entity = DialogPojo.class,
                parentColumns = "id",
                childColumns = "dialogId",
                onDelete = ForeignKey.CASCADE),
        primaryKeys = {"dialogId", "tag"})
public class TagPojo {
    @NonNull
    String dialogId;
    @NonNull
    String tag;
//other fields
}

и связываем их в единую сущность:

public class DialogWithTags {
    @Embedded
    public DialogPojo dialog;
    @Relation(parentColumn = "id", entity = TagPojo.class, entityColumn = "dialogId")
    public List<TagPojo> tags;
//other fields
}

Для получения новой сущности типа DialogWithTags нужно использовать Dao, которое будет загружать данные из таблицы DialogPojo, при этом автоматически загрузятся tags из связанной таблицы (entity = TagPojo.class):

@Dao
public interface DialogDao {
    @Query("SELECT * FROM DialogPojo WHERE id = :dialogId")
    LiveData<DialogWithTags> loadDialogBy(String dialogId);
    @Query("SELECT * FROM DialogPojo WHERE id = :dialogId")
    DialogWithTags getDialogBy(String dialogId);
}

Используя эти знания уже можно собирать звезду смерти приложение. Однако, в процессе работы могут возникнуть вопросы, ответы на которые лучше знать на подготовительных этапах.

Целостность


Как это ни странно, но запрос на получение DialogWithTags не гарантирует целостность данных. Т.е., возможна ситуация, когда DialogPojo уже загружен, а список TagPojo нет. Предупреждение о возможных проблемах появляется на этапе компиляции программы.А кто их читает, эти предупреждения? Для обеспечения целостности данных, в запрос нужно добавить аннотацию Transaction.

@Dao
public interface DialogDao {
    @Transaction @Query("SELECT * FROM DialogPojo WHERE id = :dialogId")
    LiveData<DialogWithTags> loadDialogBy(String dialogId);
    @Transaction @Query("SELECT * FROM DialogPojo WHERE id = :dialogId")
    DialogWithTags getDialogBy(String dialogId);
}

Сохранение


К сожалению, сохранить модель DialogWithTags просто так не получится. Сохранять данные нужно отдельно и, желательно, в одной транзакции, например:

@Dao
public abstract class DialogDao {
    @Transaction
    public void insert(DialogWithTags dialogWithTags) {
        insert(dialogWithTags.dialog);
        for(TagPojo tag: dialogWithTags.tags) {
            insert(tag);
        }
    }

    @Insert(onConflict = OnConflictStrategy.IGNORE)
    public abstract long insert(DialogPojo dialog);
    @Insert(onConflict = OnConflictStrategy.IGNORE)
    public abstract long insert(TagPojo tag);
    ....
}

Live Data


Самое большое разочарование ждет при использовании LiveData. Данные будут живыми только для Embedded поля dialog. Изменения для tags отслеживаться не будут. Конечно можно объявить поле tags как LiveData, но, не стоит забывать, что LiveData вернет данные только в том случае, если зарегистрирован хотя бы один обсервер.

Заключение


Как и любой фреймворк, Architecture Components решает ряд задач, избавляет разработчиков от boilerplate кода и делает жизнь прекрасней, но и добавляет своих собственных проблем. В моём случае фреймворк успешно внедрился в проект и прекрасно себя там чувствует.
Теги:
Хабы:
+9
Комментарии1

Публикации

Истории

Работа

Swift разработчик
30 вакансий
Java разработчик
358 вакансий
iOS разработчик
22 вакансии

Ближайшие события

Weekend Offer в AliExpress
Дата20 – 21 апреля
Время10:00 – 20:00
Место
Онлайн
Конференция «Я.Железо»
Дата18 мая
Время14:00 – 23:59
Место
МоскваОнлайн