#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 будет дублировать столбцы, соответствующие всем полям суперкласса.