Как реализовать наследование для объекта Room (Android, Kotlin)

#android #kotlin

#Android #kotlin

Вопрос:

Я новичок в Room и не нашел никаких сообщений, связанных с этим. У меня есть два класса: BaseModel и ChildModel. ChildModel — это класс объекта Room, а BaseModel — нет. Как мне правильно расширить базовую модель из дочерней модели? Я попытался сделать это, как в приведенном ниже коде…

Базовая модель.kt:

 @Parcelize
open class BaseModel(
    open val id: String,
    open var name: String,
    open var creator: String,
    open var dateOfLastEdit: Timestamp,
    open var contributors: List<String>,
    open var color: Int,
    open var offline: Boolean
) : Parcelable {...} 
  

ChildModel.kt (пустой конструктор, используемый для firebase):

 @Entity
@Parcelize
data class ChildModel(
    @PrimaryKey(autoGenerate = false)
    override val id: String = "",
    override var name: String = "",
    override var creator: String = "",
    @TypeConverters(DateTypeConverter::class)
    override var dateOfLastEdit: Timestamp = currentTime(),
    @TypeConverters(ListStringConverter::class)
    override var contributors: List<String> = emptyList(),
    override var color: Int = NO_COLOR,
    override var offline: Boolean = false,
    var text: String = "",
    var lastEditTextPosition: Int = 0,
    var lastEditNamePosition: Int = 0,
    var lastUserEdited: String = ""
) : Parcelable, BaseModel(id, name, creator, dateOfLastEdit, contributors, color, offline) {
    constructor() : this("", "", "", currentTime(), emptyList(), NO_COLOR, false, "", 0, 0, "") 
...
}
  

… но это выдает ошибку: «Поле имеет неуникальное имя столбца» для всех полей, которые переопределены из базовой модели. Кстати, при создании BaseModel в качестве интерфейса он успешно создается.

Мой класс базы данных:

 @Database(entities = [ChildModel::class], version = 1)
@TypeConverters(DateTypeConverter::class, ListStringConverter::class) 
    abstract class CustomDatabase : RoomDatabase() {
    abstract fun childModelDao(): ChildModelDao

    companion object {
        var INSTANCE: CustomDatabase? = null

        fun getDatabase(context: Context): CustomDatabase? {
            if (INSTANCE == null) {
                synchronized(CustomDatabase::class) {
                    INSTANCE = Room.databaseBuilder(
                        context.applicationContext,
                        CustomDatabse::class.java,
                        DATABASE
                    ).build()
                }
            }
            return INSTANCE
        }
        fun destroyDatabase() {
            INSTANCE = null
        }
    }
}
  

Ошибка не связана с обновлением версии базы данных, потому что я удалил предыдущую.
Заранее спасибо!

Ответ №1:

Хорошо, кажется, что Room каким-то образом создает два столбца с одинаковыми именами (для родительского класса и для дочернего класса) Я попытался добавить @Ignore аннотацию над каждым полем внутри класса BaseModel. Это устранило проблему, проект успешно собран, но я не уверен, что это лучший подход.

Комментарии:

1. Напрашивается вопрос — почему Room беспокоится о повторяющихся именах столбцов в этом случае? У меня может быть несколько @Entity столбцов с одинаковым именем столбца, когда наследование не задействовано. Например. @Entity User { id: Int } и @Entity Game { id: Int } , и никого это не волнует. Если @Entity класс наследует от @Entity класса, создает ли Room одну таблицу, содержащую все не игнорируемые данные, общие для обоих классов?

Ответ №2:

В случаях, когда объект наследует поля от родительского объекта, обычно проще использовать ignoredColumns свойство @Entity атрибута

Источник:https://developer.android.com/training/data-storage/room/defining-data

В примере в статье показано @Entity data class наследование от open class .

Основываясь на ответе @Anastasia Dronina, похоже, что причина использования ignoredColumns свойства @Entity атрибута заключается в том, что Room будет дублировать столбцы, соответствующие всем полям суперкласса.