← Назад к вопросам
Как связать две таблицы в Room
1.3 Junior🔥 121 комментариев
#Android компоненты#Работа с данными
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI26 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Как связать две таблицы в Room
Room — это ORM (Object-Relational Mapping) библиотека для Android, встроенная в AndroidX. Связывание таблиц осуществляется через внешние ключи (foreign keys) и специальные аннотации.
1. Определение структуры с внешним ключом
Сначала создадим две сущности (entities) с отношением один-ко-многим (User → Post):
// Таблица пользователей
@Entity(tableName = "users")
data class User(
@PrimaryKey val id: Long,
val name: String,
val email: String
)
// Таблица постов с внешним ключом на User
@Entity(
tableName = "posts",
foreignKeys = [
ForeignKey(
entity = User::class,
parentColumns = ["id"],
childColumns = ["userId"],
onDelete = ForeignKey.CASCADE, // При удалении юзера удалить посты
onUpdate = ForeignKey.CASCADE
)
],
indices = [
Index("userId") // Индекс для оптимизации запросов
]
)
data class Post(
@PrimaryKey val id: Long,
val userId: Long, // Внешний ключ
val title: String,
val content: String
)
2. Создание класса для связи данных
Для загрузки связанных данных используется специальный класс POJO:
data class UserWithPosts(
@Embedded
val user: User,
@Relation(
parentColumn = "id",
entityColumn = "userId"
)
val posts: List<Post>
)
3. Создание DAO (Data Access Object)
DAO содержит методы для работы с данными:
@Dao
interface UserPostDao {
// Получить пользователя со всеми его постами
@Transaction
@Query("SELECT * FROM users WHERE id = :userId")
suspend fun getUserWithPosts(userId: Long): UserWithPosts
// Получить все пользователей со их постами
@Transaction
@Query("SELECT * FROM users")
suspend fun getAllUsersWithPosts(): List<UserWithPosts>
// Вставить пользователя
@Insert
suspend fun insertUser(user: User)
// Вставить пост
@Insert
suspend fun insertPost(post: Post)
// Обновить пост
@Update
suspend fun updatePost(post: Post)
// Удалить пост
@Delete
suspend fun deletePost(post: Post)
}
4. Создание Database класса
@Database(
entities = [User::class, Post::class],
version = 1,
exportSchema = false
)
abstract class AppDatabase : RoomDatabase() {
abstract fun userPostDao(): UserPostDao
companion object {
@Volatile
private var INSTANCE: AppDatabase? = null
fun getDatabase(context: Context): AppDatabase {
return INSTANCE ?: synchronized(this) {
Room.databaseBuilder(
context.applicationContext,
AppDatabase::class.java,
"app_database"
).build().also { INSTANCE = it }
}
}
}
}
5. Использование в коде
class UserRepository(private val dao: UserPostDao) {
suspend fun loadUserWithPosts(userId: Long): UserWithPosts {
return dao.getUserWithPosts(userId)
}
suspend fun addPost(userId: Long, title: String, content: String) {
val post = Post(
id = System.currentTimeMillis(),
userId = userId,
title = title,
content = content
)
dao.insertPost(post)
}
}
6. Типы отношений в Room
One-to-One (Один-к-одному):
data class UserWithProfile(
@Embedded val user: User,
@Relation(parentColumn = "id", entityColumn = "userId")
val profile: Profile
)
One-to-Many (Один-ко-многим): — как показано выше
Many-to-Many (Много-ко-многим):
// Связующая таблица
@Entity(
tableName = "user_book_junction",
primaryKeys = ["userId", "bookId"],
foreignKeys = [
ForeignKey(entity = User::class, parentColumns = ["id"], childColumns = ["userId"]),
ForeignKey(entity = Book::class, parentColumns = ["id"], childColumns = ["bookId"])
]
)
data class UserBook(val userId: Long, val bookId: Long)
data class UserWithBooks(
@Embedded val user: User,
@Relation(
parentColumn = "id",
entityColumn = "id",
associateBy = Junction(UserBook::class, parentColumn = "userId", entityColumn = "bookId")
)
val books: List<Book>
)
Важные моменты
- @Transaction гарантирует, что запрос и загрузка связей выполнятся в одной транзакции
- ForeignKey.CASCADE автоматически удаляет подчиненные записи
- @Embedded встраивает поля сущности в родительский класс
- Indices улучшают производительность запросов
- Room работает асинхронно (suspend функции)
Это стандартный способ работы со связанными данными в Android.