Невозможно найти сеттер для поля - используя базу данных Kotlin с комнатой
Я интегрируюсь с библиотекой Persistence. У меня есть класс данных в Kotlin:
@Entity(tableName = "story")
data class Story (
@PrimaryKey val id: Long,
val by: String,
val descendants: Int,
val score: Int,
val time: Long,
val title: String,
val type: String,
val url: String
)
Аннотации @Entity
и @PrimaryKey
предназначены для библиотеки Room. Когда я пытаюсь построить, он терпит неудачу с ошибкой:
Error:Cannot find setter for field.
Error:Execution failed for task ':app:compileDebugJavaWithJavac'.
> Compilation failed; see the compiler error output for details.
Я также попытался предоставить конструктор по умолчанию:
@Entity(tableName = "story")
data class Story (
@PrimaryKey val id: Long,
val by: String,
val descendants: Int,
val score: Int,
val time: Long,
val title: String,
val type: String,
val url: String
) {
constructor() : this(0, "", 0, 0, 0, "", "", "")
}
Но это не работает. Следует отметить, что он работает, если я конвертирую этот класс Kotlin в класс Java с помощью геттеров и сеттеров. Любая помощь приветствуется!
Ответы
Ответ 1
Поскольку ваши поля отмечены val
, они фактически окончательны и не имеют полей настройки.
Попробуйте отключить val
с помощью var
.
Вам также может потребоваться инициализировать поля.
@Entity(tableName = "story")
data class Story (
@PrimaryKey var id: Long? = null,
var by: String = "",
var descendants: Int = 0,
var score: Int = 0,
var time: Long = 0L,
var title: String = "",
var type: String = "",
var url: String = ""
)
Ответ 2
Эй, я не знаю, знают ли все или нет, но у вас не может быть столбца, начинающегося с is
в Room
.
Например, вы не можете иметь это
@Entity(tableName = "user")
data class User (
@PrimaryKey var id: Long? = null,
var userName: String = "",
var isConnectedToFB: Boolean = false,
)
Ответ 3
Существует проблема в генерации Java-библиотеки библиотеки db.
Я использовал необязательное поле isFavorite
. Это дает мне ту же ошибку, после чего я изменяю имя поля на favorite
затем компилируемое.
перед var isFavorite: Int? = 0,
var isFavorite: Int? = 0,
после изменения отлично работает var favorite: Int? = 0,
var favorite: Int? = 0,
спасибо
Ответ 4
Это ошибка и исправлена в комнате 2.1.0-alpha01
https://developer.android.com/jetpack/docs/release-notes#october_8_2018
Исправление ошибок
- Теперь Room будет правильно использовать основной конструктор Kotlins в классах данных, избегая необходимости объявлять поля как переменные. б /105769985
Ответ 5
Согласно fooobar.com/questions/252524/... если у вас есть автоматически сгенерированный первичный ключ, вы должны написать так:
@Entity(tableName = "story")
data class Story (
val by: String,
val descendants: Int,
val score: Int,
val time: Long,
val title: String,
val type: String,
val url: String
) {
@PrimaryKey(autoGenerate = true)
var id: Int = 0
}
Обратите внимание, что @PrimaryKey
написан внутри тела класса и содержит модификатор var
.
Если позже вы захотите обновить строку в базе данных с другими параметрами, используйте эти строки:
val newStory = story.copy(by = "new author", title = "new title") // Cannot use "id" in object cloning
newStory.id = story.id
dao.update(newStory)
ОБНОВИТЬ
Я до сих пор не использую AndroidX, а Room - это "android.arch.persistence.room:runtime:1.1.1".
Вы можете расширить этот класс от Serializable
. Но если вы захотите расширить его из Parcelable
, вы получите предупреждение (через переменную id
): Property would not be serialized inro a 'Parcel'. Add '@IgnoredOnParcel' annotation to remove this warning
Property would not be serialized inro a 'Parcel'. Add '@IgnoredOnParcel' annotation to remove this warning
:
![enter image description here]()
Затем я переместил id
из тела в конструктор. В Kotlin я использую @Parcelize
для создания классов Parcelable
:
@Parcelize
@Entity(tableName = "story")
data class Story (
@PrimaryKey(autoGenerate = true)
var id: Int = 0,
val by: String,
val descendants: Int,
val score: Int,
val time: Long,
val title: String,
val type: String,
val url: String
) : Parcelable
Ответ 6
Была эта ошибка в Java.
Вы не можете иметь столбец, начинающийся с is
или is_
в Java.
Попробуйте переименовать столбец.
Другое решение:
Вы должны либо передать поле в конструктор и инициализировать его аргументом конструктора, либо создать для него установщик.
Пример:
public MyEntity(String name, ...) {
this.name = name;
...
}
public void setName(String name) {
this.name = name;
}
Ответ 7
Другой причиной этого может быть именование поля. Если вы используете какой-либо из предопределенных ключевых слов, вы получите ту же ошибку.
Например, вы не можете назвать свой столбец "is_active".
Ссылка: http://www.sqlite.org/lang_keywords.html
Ответ 8
Просто обновление, если кто-то сталкивается с этой темой в 2019 году, потратив часы на то, чтобы выяснить, почему это должно работать, но это не так.
Использование val
работает должным образом, если вы используете версию androidx.room:room-<any>:2.*
(androidx.room:room-<any>:2.*
), но не работает при использовании старого android.arch.persistence.room:<any>:1.1.1
и кажется, что версия 2.*
не была выпущена в этом последнем репо.
Редактировать: опечатки
Ответ 9
Если вы хотите, чтобы для вашей сущности была доступна неизменность val
, это возможно.
- Вам следует обновить текущую версию комнаты AndroidX.
- Проверьте наличие связанной проблемы здесь, она помечена как не будет устранена
- Теперь они выпустили исправление, связанное с проблемой с версией 2.0.0-бета01
- Теперь вы можете использовать неизменный
val
со default value
например:
@Entity("tbl_abc")
data class Abc(
@PrimaryKey
val id: Int = 0,
val isFavourite: Boolean = false
)
Ранее приведенный фрагмент кода выдавал ошибку Cannot find setter for field
. Переход на var
- отличный обходной путь, но я предпочитаю, чтобы класс сущности был неизменным при внешнем вызове.
Ответ 10
Теперь вы можете начать свое поле с is
, но у вас не может быть номера рядом с is
, например: is2FooSelected
, вы должны переименовать в isTwoFooSelected
.