Room

https://developer.android.com/training/data-storage/room
https://developer.android.com/training/data-storage/room/defining-data
https://developer.android.com/training/data-storage/room/accessing-data
https://developer.android.com/training/data-storage/room/relationships
https://developer.android.com/training/data-storage/room/async-queries
https://developer.android.com/training/data-storage/room/creating-views
https://developer.android.com/training/data-storage/room/prepopulate
https://developer.android.com/training/data-storage/room/migrating-db-versions
https://developer.android.com/training/data-storage/room/testing-db
https://developer.android.com/training/data-storage/room/referencing-data
https://developer.android.com/training/data-storage/room/sqlite-room-migration
https://developer.android.com/training/data-storage/room/room-kmp-migration

Абстракция над SQLite для надежного доступа к базе данных.

Flow не триггерится после обновления поля в Room с использованием Relation

В таком случае обновлять вложенные DTO нужно через аннотацию Update.

@Update
suspend fun update(boardDb: BoardDb)

Select in range

@Query("SELECT * FROM medias WHERE type IN (:types)")
fun getItems(types: List<Type>): Flow<List<MediaDb>>

Is Exist

@Query("SELECT EXISTS(SELECT * FROM posts WHERE postId = :postId)")
suspend fun isExist(postId: Int): Boolean

Count

@Query("SELECT COUNT(*) FROM boosts WHERE active = 0")
fun availableBoostsCount(): Flow<Int>

ForeignKey

Внешний ключ для другой Entity. Выстраивает отношения при изменении базы данных. SQLite требует чтобы столбцы на которые ссылаются были частью уникального индекса в родительской таблице или первичного ключа этой таблицы.

@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)
}
@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
}
Room. Вопросы на собесе
  1. Что такое Room и какие преимущества она предоставляет по сравнению с прямым использованием SQLite?
  1. Какие основные компоненты Room и как они взаимодействуют?
  1. Что произойдет, если не настроить миграцию при изменении схемы базы данных?
  1. Как работать с отношениями между сущностями в Room (например, “один ко многим” или “многие ко многим”)?
  1. Как использовать типы данных, не поддерживаемые напрямую Room, такие как Date или List?
  1. Как Room обрабатывает конфликты при вставке или обновлении данных?
  1. Как работает каскадное удаление?

    Каскадное удаление в Room позволяет автоматически удалять связанные записи в базе данных при удалении основной записи. Это реализуется с помощью аннотации @ForeignKey с параметром onDelete = ForeignKey.CASCADE в определении связи между сущностями.

  1. Какие есть базы данных кроме Room?

    SQLite, Realm, SQLDelight