Какие основные компоненты Room используются для работы с базой данных
Что проверяют
Знаете ли вы Room как рабочий инструмент, а не как три аннотации из документации. Следом обычно спрашивают про миграции при обновлении приложения и про то, как получать данные реактивно, без ручного обновления экрана.
Как отвечать
Три основных компонента и то, что вокруг них:
@Entity: класс, описывающий таблицу.@PrimaryKey(autoGenerate = true),@ColumnInfoдля имени колонки,indicesиforeignKeysв параметрах аннотации,@Ignoreдля полей вне таблицы. Вложенные объекты разворачиваются через@Embedded, нестандартные типы вроде дат и enum через@TypeConverter;@Dao: интерфейс с методами доступа.@InsertсonConflict,@Update,@Delete,@Upsert,@Queryс SQL, который проверяется при компиляции: опечатка в имени колонки ломает сборку, а не приложение. Методы делаютsuspend, а для наблюдения возвращаютFlow<List<User>>: Room сам переизлучит данные при изменении таблицы;@Database: абстрактный наследникRoomDatabaseсо списком сущностей, номеромversionи методами, отдающими DAO. Создаётся черезRoom.databaseBuilder()один раз на процесс, обычно через DI;- связи: класс с родителем под
@Embeddedи дочерним списком под@Relation, такой запрос в DAO помечают@Transaction; - миграции:
Migration(1, 2)сexecSQL()черезaddMigrations(), либо@AutoMigrationдля простых изменений, для неё нужен экспорт схемыexportSchema = true. Тестируются черезMigrationTestHelper.
Код Room генерирует при сборке, в новых проектах процессор подключают через KSP, а не kapt. Запрос на главном потоке по умолчанию бросает исключение.
Где спотыкаются
Меняют сущность и поднимают version, но не пишут миграцию. Приложение падает на старте, а «быстрое решение» fallbackToDestructiveMigration() на проде молча стирает данные пользователей.
Создают экземпляр базы в каждом репозитории. Это дорого, а изменения, сделанные через один экземпляр, могут не дойти до подписчиков Flow другого.
Делают несколько связанных записей без транзакции. При сбое посередине в базе остаётся половина данных, поэтому такие операции оборачивают в метод с @Transaction или в withTransaction { }.