Ich bin in die Room Persistence Library integriert. Ich habe eine Datenklasse in Kotlin wie:
@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
)
Die @Entity
und @PrimaryKey
Anmerkungen gelten für die Raumbibliothek. Wenn ich versuche zu bauen, schlägt es mit Fehler fehl:
Error:Cannot find setter for field.
Error:Execution failed for task ':app:compileDebugJavaWithJavac'.
> Compilation failed; see the compiler error output for details.
Ich habe auch versucht, einen Standardkonstruktor bereitzustellen:
@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, "", "", "")
}
Das funktioniert aber nicht so gut. Zu beachten ist, dass es funktioniert, wenn ich diese Kotlin-Klasse in eine Java-Klasse mit Getter und Setter konvertiere. Jede Hilfe wird geschätzt!
Antworten:
Da Ihre Felder mit markiert sind
val
, sind sie effektiv endgültig und haben keine Setterfelder.Versuchen Sie das
val
mit auszutauschenvar
. Möglicherweise müssen Sie auch die Felder initialisieren.@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 = "" )
BEARBEITEN
Die obige Lösung ist eine allgemeine Lösung für diesen Fehler in Kotlin, wenn Kotlin mit anderen Java-Bibliotheken wie Hibernate verwendet wird, wo ich dies ebenfalls gesehen habe. Wenn Sie die Unveränderlichkeit von Room beibehalten möchten, lesen Sie einige der anderen Antworten, die möglicherweise spezifischer für Ihren Fall sind.
In einigen Fällen Unveränderlichkeit mit Java - Bibliotheken ist einfach nicht funktioniert und während traurig Entwickler Geräusche, haben Sie , dass wechseln
val
für einenvar
leider.quelle
Hey, ich weiß nicht, ob jeder weiß oder nicht, aber Sie können keine Spalte haben, die von
is
in beginntRoom
. Zum Beispiel kann man so etwas nicht haben@Entity(tableName = "user") data class User ( @PrimaryKey var id: Long? = null, var userName: String = "", var isConnectedToFB: Boolean = false, )
quelle
kotlin
du solche Felder nicht haben kannst. (nach oben abstimmen) Jedenfalls istjava
mir aufgefallen, dass es erlaubt ist.Laut https://stackoverflow.com/a/46753804/2914140 sollten Sie Folgendes schreiben, wenn Sie einen automatisch generierten Primärschlüssel haben:
@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 }
Beachten Sie, dass dies
@PrimaryKey
im Klassenkörper geschrieben ist und den Modifikator enthältvar
.Wenn Sie später eine Zeile in einer Datenbank mit anderen Parametern aktualisieren möchten, verwenden Sie die folgenden Zeilen:
val newStory = story.copy(by = "new author", title = "new title") // Cannot use "id" in object cloning newStory.id = story.id dao.update(newStory)
AKTUALISIEREN
Ich benutze AndroidX immer noch nicht und Room ist 'android.arch.persistence.room:runtime:1.1.1'.
Sie können diese Klasse von erweitern
Serializable
. Wenn Sie es jedoch erweitern möchtenParcelable
, erhalten Sie eine Warnung (überid
Variable)Property would not be serialized inro a 'Parcel'. Add '@IgnoredOnParcel' annotation to remove this warning
::Dann habe ich eine
id
vom Körper zum Konstruktor verschoben . In Kotlin@Parcelize
erstelle ichParcelable
Klassen:@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
quelle
Es gibt ein Problem bei der Generierung von Java-Code in der Room-DB-Bibliothek.
Ich habe ein optionales Feld verwendet
isFavorite
. Es gibt mir den gleichen Fehler, dann ändere ich meinen Feldnamen infavorite
dann kompiliert.vorher
var isFavorite: Int? = 0,
nach dem wechseln funktioniert gutvar favorite: Int? = 0,
Dankequelle
Hatte diesen Fehler in Java.
Sie können keine Spalte haben, die mit
is
oderis_
in Java beginnt .Versuchen Sie, die Spalte umzubenennen.
Eine andere Lösung:
Sie müssen entweder das Feld im Konstruktor übergeben und mit dem Konstruktorargument initialisieren oder einen Setter dafür erstellen.
Beispiel:
public MyEntity(String name, ...) { this.name = name; ... } public void setName(String name) { this.name = name; }
quelle
Dies ist ein Fehler und wurde in Room behoben
2.1.0-alpha01
https://developer.android.com/jetpack/docs/release-notes#october_8_2018
quelle
2.1.0-alpha03
aber ich bekomme immer noch diesen FehlerIch habe festgestellt, dass eine weitere Ursache für diesen Kompilierungsfehler in der Verwendung der
@Ignore
Annotation des Raums für Felder Ihrer Entitätsdatenklasse liegen kann:@Entity(tableName = "foo") data class Foo( // Okay @PrimaryKey val id: String, // Okay val bar: String, // Annotation causes compilation error, all fields of data class report // the "Cannot find setter for field" error when Ignore is present @Ignore val causeserror: String )
Der gleiche Fehler scheint auch bei der Verwendung der
@Transient
Annotation aufzutreten.Ich habe dieses Problem bei der Verwendung
2.2.2
der Room- Version festgestellt :// build.gradle file dependencies { ... kapt "androidx.room:room-compiler:2.2.2" ... }
Hoffe das hilft jemandem!
quelle
@Ignore
aus Feldern meiner Entitätsklasse entfernen . Vielleicht haben Sie@Ignore
Felder in einer oder mehreren Ihrer Entitätsklassen eingefügt?@Ignore
Anmerkung) nicht in der Datenbank vorhanden ist .Wenn Sie ein
@Ignore
Feld im Datenklassenkonstruktor haben, müssen Sie es wie folgt in den Klassenkörper verschieben:@Entity(primaryKeys = ["id"]) data class User( @field:SerializedName("id") val id: Int, @field:SerializedName("name") val name: String, @field:SerializedName("age") val age: Int ) { @Ignore val testme: String? }
Alle Kudos gehen an marianperca auf GitHub: https://github.com/android/architecture-components-samples/issues/421#issuecomment-442763610
quelle
Sie können versuchen, die ID-Variable in einen anderen Namen umzubenennen. Es hat bei mir funktioniert;
var id: Long? = null
zu
var workerId: Long? = null
Wenn Sie einen Namen als ID angeben müssen und eine Nachrüstung verwenden, müssen Sie möglicherweise SerializedName ("ID") hinzufügen.
quelle
Eine weitere Ursache hierfür kann die Benennung des Feldes sein. Wenn Sie eines der vordefinierten Schlüsselwörter verwenden, wird der gleiche Fehler angezeigt. Beispielsweise können Sie Ihre Spalte nicht "is_active" nennen.
Referenz: http://www.sqlite.org/lang_keywords.html
quelle
Nur ein Update, wenn jemand 2019 auf diesen Thread stößt, nachdem er stundenlang online darüber nachgedacht hat, warum dies funktionieren sollte, aber es funktioniert nicht.
Die Verwendung
val
funktioniert wie erwartet, wenn Sie die AndroidX-Version (androidx.room:room-<any>:2.*
) verwenden, jedoch nicht, wenn Sie die alte verwenden,android.arch.persistence.room:<any>:1.1.1
und es scheint, dass die Version2.*
für dieses letztere Repo nicht veröffentlicht wurde.Bearbeiten: Tippfehler
quelle
android.arch.persistence.room
.Wenn Sie möchten, dass die
val
Unveränderlichkeit für Ihr Unternehmen verfügbar ist, ist dies möglich.val
mitdefault value
zB:@Entity("tbl_abc") data class Abc( @PrimaryKey val id: Int = 0, val isFavourite: Boolean = false )
Zuvor wird das obige Snippet einen Fehler von auslösen
Cannot find setter for field
. Das Wechseln invar
ist eine großartige Problemumgehung, aber ich bevorzuge, dass die Entitätsklasse von einem externen Aufruf unveränderlich istquelle
Dieser Fehler wird ausgelöst, wenn Ihre Spalte mit Is beginnt:
@ColumnInfo(name = "IsHandicapLeague") @NonNull var isHandicapLeague: String = "Y"
Fügen Sie eine Standardfunktion set () hinzu, um sie zu entfernen
fun setIsHandicapLeague(flag:String) { isHandicapLeague = flag }
quelle
Sie können Ihr Feld jetzt mit beginnen,
is
aber Sie können keine Nummer neben deris
gleichen haben:is2FooSelected
Sie müssen umbenennen inisTwoFooSelected
.quelle
Verwenden Sie einfach var anstelle von val und machen Sie es öffentlich, wenn Sie ein privates Schlüsselwort verwenden.
@Entity(tableName = "story") data class Story ( @PrimaryKey val id: Long, var by: String, var descendants: Int, var score: Int, var time: Long, var title: String, var type: String, var url: String )
quelle