Room
Room
Абстракция над SQLite для надежного доступа к базе данных.
Получить количество записей в таблице
@Query("SELECT COUNT(*) FROM users")
fun usersCount(): Flow<Int>
Проверить существование записи в таблице
@Query("SELECT EXISTS(SELECT * FROM users WHERE userId = :userId)")
suspend fun isExist(userId: Int): Boolean
Фильтр по диапазону значений
@Query("SELECT * FROM users WHERE type IN (:ids)")
fun getUsers(ids: List<Int>): Flow<List<UserDb>>
Обновление значения
Если Flow
не триггерится после обновления значения с использованием Relation.
@Update
suspend fun update(userDb: UserDb)
@Database
Маркирует класс-наследник RoomDatabase
для конфигурирования базы данных. Должен быть абстрактным.
@Database(entities = [User::class], version = 1)
abstract class AppDatabase: RoomDatabase() {
abstract fun userDao(): UserDao
}
@Entity
Сущность данных. Объект данных в Room. Каждый объект - отдельная таблица в базе данных. Каждый экземпляр объекта - строка в таблице.
@Entity
data class User(
@PrimaryKey val userId: Int,
val name: String,
@ColumnInfo(name = "user_age") val age: Int
)
@Dao
Data access object. Предоставляет методы для взаимодействия с данными в таблице.
@Dao
interface UserDao {
@Query("SELECT * FROM user")
fun getAll(): List<User>
@Insert
fun insertAll(vararg users: User)
@Delete
fun delete(user: User)
}
@ForeignKey
В Room внешние ключи (ForeignKey) используются для создания связей между таблицами, обеспечивая целостность данных. При объявлении внешнего ключа в сущности (Entity) указываются поля, которые будут ссылаться на другие таблицы. Это позволяет реализовать отношения, такие как один ко многим.
@Entity
data class Order(
@PrimaryKey val orderId: Long,
@ForeignKey(entity = Customer::class, parentColumns = ["customerId"], childColumns = ["customerId"]) val customerId: Long
)
@Entity
data class Customer(
@PrimaryKey val customerId: Long,
val name: String
)
@RewriteQueriesToDropUnusedColumns
Используется с аннотацией Query
и позволяет извлечь из таблицы только те столбцы которые указаны в модели для ответа.
data class NameAndLastName (
val name: String,
val lastName: String
)
@Dao
interface MyDao {
@Query("SELECT * FROM User")
public fun getAll(): List<NameAndLastName> // извлечет все поля, не только name и lastName
}
@Dao
interface MyDao {
@RewriteQueriesToDropUnusedColumns
@Query("SELECT * FROM User")
fun getAll(): List<NameAndLastName> // извлечет только name и lastName
}
Вопросы на собесе (16)
- Что такое Room?
Библиотека для работы с базами данных в Android, которая предоставляет абстракцию над
SQLite
.
- Преимущества Room по сравнению с SQLite?
• Типобезопасность — Room проверяет запросы на этапе компиляции.
• Упрощенное взаимодействие — благодаря DAO можно использовать аннотации для определения запросов без необходимости писать
SQL
.• Автоматическая миграция — упрощает обновление схемы базы данных.
• Поддержка
LiveData
и Coroutines — позволяет работать с асинхронностью и реактивным программированием.• Упрощение обработки отношений — поддержка «один ко многим» и «многие ко многим».
- Какие основные компоненты Room?
•
@Entity
- класс, представляющий таблицу в базе данных.•
@Dao
(Data Access Object) - интерфейс для определения методов доступа к данным.•
@Database
- абстрактный класс, который объединяет все сущности и DAO, а также управляет базой данных.
- Как работают аннотации @Query @Insert @Update @Delete в Room?
Используются для определения
SQL
-запросов к базе данных.
- Что произойдет, если не настроить миграцию при изменении схемы базы данных?
Приложение может выдать исключение
SQLiteException
, и база данных не сможет открыться. Это приведет к сбою приложения, так как Room не сможет сопоставить новую структуру с существующей.
- Как работать с отношениями между сущностями в Room (например, «один ко многим» или «многие ко многим»)?
• Один ко многим: создайте две сущности. В основной сущности добавьте поле для идентификатора связанной сущности. Используйте аннотацию
@Relation
для создания списка связанных объектов в основной сущности.• Многие ко многим: создайте третью сущность, которая будет представлять связь между двумя сущностями (состоящую из двух полей идентификаторов). Затем используйте аннотацию
@Relation
в обеих сущностях для определения связи через эту промежуточную таблицу.
- Как использовать типы данных, не поддерживаемые напрямую Room, такие как Date или List?
Использовать
@TypeConverter
.
- Как Room обрабатывает конфликты при вставке или обновлении данных?
Room обрабатывает конфликты при вставке или обновлении данных с помощью стратегии разрешения конфликтов. По умолчанию используется стратегия
IGNORE
, но можно указать другие, такие какREPLACE
илиABORT
. Это позволяет управлять тем, как Room будет реагировать на конфликты, например, игнорировать конфликтующие записи или заменять их новыми данными.
- Как объединить несколько таблиц в Room?
Использовать аннотацию
@Relation
в Entity-классах для отображения отношений «один ко многим» или «многие ко многим», либо использовать запросы сJoin
в DAO для выполнения более сложных операций с несколькими таблицами.
- Как работает каскадное удаление в Room?
Каскадное удаление в Room позволяет автоматически удалять связанные записи в базе данных при удалении основной записи. Это реализуется с помощью аннотации
@ForeignKey
с параметромonDelete = ForeignKey.CASCADE
в определении связи между сущностями.
- Какие есть базы данных кроме Room?
•
SQLite
•
Realm
•
SQLDelight
- Чем Room отличается от Realm?
Room — это библиотека для работы с
SQLite
и реляционными данными, интегрированная с архитектурой Android.Realm
— собственная база данных, работающая с объектами напрямую (NoSQL
), предлагающая высокую производительность, но с ограничениями по миграции и сложным запросам.
- Как связать 2 Entity между собой?
Использовать аннотацию
@Relation
для создания связи между ними. Например, можно создать один класс для родительской сущности и другой для дочерней.
- Как файл базы данных Room хранится в Android?
Файл базы данных Room хранится в каталоге приложения на устройстве Android, обычно по пути
/data/data/your.package.name/databases/your_database_name.db
. Этот файл доступен только приложению, которое его создало, и содержит все таблицы, индексы и данные, которые вы определили в своих Entity-классах. Room автоматически управляет созданием и обновлением базы данных при изменении схемы.
- Почему файл базы данных Room не может прочитать другое приложение?
Из-за механизма безопасности Android, который изолирует данные приложений. Каждое приложение работает в своем собственном контейнере, и доступ к файловой системе ограничен. По умолчанию файлы в каталоге
/data/data/your.package.name/
защищены, и другие приложения не имеют разрешения на их чтение или запись, что предотвращает несанкционированный доступ к данным.
- Какие виды связей существуют в базах данных?
• Один к одному (1:1) — связь между двумя таблицами, где каждой записи в одной таблице соответствует одна запись в другой.
• Один ко многим (1:N) — связь, где одной записи в таблице А соответствуют несколько записей в таблице B.
• Многие к одному (N:1) — несколько записей из одной таблицы могут ссылаться на одну запись в другой.
• Многие ко многим (M:N) — связь, в которой записи из одной таблицы могут соответствовать множеству записей в другой, и наоборот.