Столбец неправильно отображен в Android Room при объединении нескольких таблиц с совпадающими именами столбцов через таблицу соединений

#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>>
 

В будущем могут возникнуть проблемы с этим. Я буду публиковать обновления, если это произойдет.