#android #kotlin #android-room
#Android #kotlin #android-room
Вопрос:
У меня есть следующий объект:
@Entity(tableName = "category",
foreignKeys = [ForeignKey(entity = PlannableItemEntity::class,
parentColumns = ["plannable_item_id"],
childColumns = ["plannable_item_id"],
onDelete = ForeignKey.CASCADE)],
indices = [Index(value = ["plannable_item_id"], unique = true)])
data class CategoryEntity(
@PrimaryKey(autoGenerate = true) @ColumnInfo(name = "category_id") var id: Long = 0L,
@ColumnInfo(name = "plannable_item_id") var plannableItemID: Long,
@ColumnInfo var name: String?) {
fun toCategory(): Category {
Log.d("CategoryEntity", "toCategory: $this")
return Category(id, name!!)
}
companion object {
fun fromCategory(category: Category): CategoryEntity? {
val plannableItem = category.plannableItem
if (plannableItem == null) {
Log.w("CategoryEntity",
"Passed category has a null reference: plannableItem. Please, pass a full category.")
return null
}
return CategoryEntity(id = category.id,
plannableItemID = plannableItem.id,
name = category.name)
}
}
}
При выборе этого через
private const val SAF = "SELECT * FROM"
@Dao
interface CategoryDao : GenericInsertUpdateDeleteDao<CategoryEntity> {
@Query("$SAF category")
fun getAll(): Flow<List<CategoryEntity>>
// ...
}
Это работает нормально (я получаю все из БД, как и ожидалось).
Однако, когда я пытаюсь получить таблицу вместе со связанными таблицами, используя этот объект:
data class CategoryFullWithActivities(
@Embedded val categoryEntity: CategoryEntity,
@Relation(
parentColumn = "plannable_item_id",
entityColumn = "plannable_item_id"
) val plannableItemEntity: PlannableItemEntity,
@Relation(
parentColumn = "category_id",
entityColumn = "activity_id",
associateBy = Junction(ActivityCategoryCrossRef::class)
) val activityEntities: List<ActivityEntity>? = null
) {
fun toCategory(): Category {
Log.d("CatFullWActivities", "toCategory: $this")
val category = categoryEntity.toCategory()
category.activities = activityEntities?.map { it.toActivity() }?.toMutableList()
return category
}
}
используя этот запрос:
@Transaction
@Query("""SELECT c.*, a.*, pi.*
FROM category c
JOIN plannable_item pi
ON pi.plannable_item_id = c.plannable_item_id
LEFT JOIN activity_category_xref xref
ON xref.category_id = c.category_id
LEFT JOIN activity a
ON xref.activity_id = a.activity_id""")
fun getAllCategoriesWithActivities(): Flow<List<CategoryFullWithActivities>>
Код компилируется, НО categoryEntity.name
заполняется как null.
Содержимое базы данных выглядит следующим образом:
category
:
category_id | plannable_item_id | Имя |
---|---|---|
-1 | 2 | Категория 1 |
-2 | 3 | Категория 2 |
plannable_item
:
plannable_item_id |
---|
2 |
3 |
В activity
таблице соединений есть записи, НО в настоящее время нет записи activity_category_xref
. Это допустимая ситуация, и в этом случае значение CategoryFullWithActivities.activityEntities
должно быть просто null. Но в любом случае это не проблема — происходит то, что in CategoryFullWithActivities
categoryEntity.name
каждый раз имеет значение null .
Возможно, стоит отметить, что ActivityEntity
он также содержит поле name
. То же самое с таблицей, например. activity.name
.
Тем не менее, Room не может это понять? Я думал об использовании префиксов, но, видимо, они поддерживаются только при использовании @Embedded
, и я не смог заставить это работать с таблицей соединений.
Комментарии:
1. Таблицы отображаются в формате предварительного просмотра правильно… Я постараюсь это исправить. (РЕДАКТИРОВАТЬ: готово)
Ответ №1:
Похоже, что выбор каждого значения в явном виде и добавление префикса к объединенным таблицам сработали (хотя я не уверен на 100%, почему):
@Transaction
@Query("""SELECT c.category_id,
c.name,
c.plannable_item_id,
a.activity_id,
a.plannable_item_id AS activity_plannable_item_id,
a.name AS activity_name,
a.is_formally_tracked AS activity_is_formally_tracked,
a.default_measurement_type_id AS activity_default_measurement_type_id,
pi.plannable_item_id
FROM category c
JOIN plannable_item pi
ON pi.plannable_item_id = c.plannable_item_id
LEFT JOIN activity_category_xref xref
ON xref.category_id = c.category_id
LEFT JOIN activity a
ON xref.activity_id = a.activity_id""")
fun getAllCategoriesWithActivities(): Flow<List<CategoryFullWithActivities>>
В будущем могут возникнуть проблемы с этим. Я буду публиковать обновления, если это произойдет.