J'intègre la bibliothèque de persistance de salle. J'ai une classe de données à Kotlin comme:
@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
)
Le @Entity
et @PrimaryKey
Les annotations concernent la bibliothèque de salles. Quand j'essaye de construire, ça échoue avec une erreur:
Error:Cannot find setter for field.
Error:Execution failed for task ':app:compileDebugJavaWithJavac'.
> Compilation failed; see the compiler error output for details.
J'ai aussi essayé de fournir un constructeur par défaut:
@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, "", "", "")
}
Mais ça ne marche pas aussi bien. Une chose à noter est que cela fonctionne si je convertis cette classe Kotlin en une classe Java avec des accesseurs et des passeurs. Toute aide est appréciée!
Puisque vos champs sont marqués de val
, ils sont en réalité finaux et n’ont pas de champs de définition.
Essayez de changer le val
avec var
. Vous devrez peut-être également initialiser les champs.
@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 = ""
)
Hé, je ne sais pas si tout le monde sait ou non, mais vous ne pouvez pas avoir de colonne qui commence de is
dans Room
. Par exemple, vous ne pouvez pas avoir comme ça
@Entity(tableName = "user")
data class User (
@PrimaryKey var id: Long? = null,
var userName: String = "",
var isConnectedToFB: Boolean = false,
)
Il y a un problème dans la bibliothèque de base de données room Java.
J'utilisais le champ optionnel isFavorite
. Cela me donne la même erreur puis je change le nom de mon champ en favorite
puis je le compile.
avant var isFavorite: Int? = 0,
après avoir bien travaillé var favorite: Int? = 0,
Merci
Selon https://stackoverflow.com/a/46753804/291414 si vous avez une clé primaire générée automatiquement, vous devez écrire ceci:
@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
}
Notez que @PrimaryKey
est écrit dans le corps de la classe et contient le modificateur var
.
Si vous souhaitez par la suite mettre à jour une ligne dans une base de données avec des paramètres différents, utilisez ces lignes:
val newStory = story.copy(by = "new author", title = "new title") // Cannot use "id" in object cloning
newStory.id = story.id
dao.update(newStory)
MISE À JOUR
Je n'utilise toujours pas AndroidX, et Room est "Android.Arch.persistence.room:runtime:1.1.1".
Vous pouvez étendre cette classe de Serializable
. Mais si vous voulez le prolonger de Parcelable
, vous recevrez un avertissement (sur id
variable): Property would not be serialized inro a 'Parcel'. Add '@IgnoredOnParcel' annotation to remove this warning
:
Ensuite, j'ai déplacé un id
du corps au constructeur. Dans Kotlin, j'utilise @Parcelize
pour créer Parcelable
classes:
@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
Ceci est un bug et est corrigé dans Room 2.1.0-alpha01
https://developer.Android.com/jetpack/docs/release-notes#october_8_2018
Corrections de bugs
- Room utilisera désormais correctement le constructeur principal de Kotlin dans les classes de données, évitant ainsi de déclarer les champs en tant que vars. b/105769985
Avait cette erreur en Java.
Vous ne pouvez pas avoir une colonne commençant par is
ou is_
en Java.
Essayez de renommer la colonne.
Une autre solution:
Vous devez soit passer le champ dans le constructeur et l'initialiser avec l'argument constructeur, soit créer un outil de définition pour celui-ci.
Exemple:
public MyEntity(String name, ...) {
this.name = name;
...
}
public void setName(String name) {
this.name = name;
}
Si vous voulez que l'immutabilité de val
soit disponible pour votre entité, c'est possible.
val
avec default value
par exemple:@Entity("tbl_abc")
data class Abc(
@PrimaryKey
val id: Int = 0,
val isFavourite: Boolean = false
)
Auparavant, l’extrait ci-dessus lève une erreur de Cannot find setter for field
. Changer en var
est une excellente solution de contournement, mais je préfère que la classe d'entités soit immuable à partir d'une invocation externe
Une autre cause peut être la dénomination du champ. Si vous utilisez l'un des mots-clés prédéfinis, vous obtiendrez la même erreur. Par exemple, vous ne pouvez pas nommer votre colonne "is_active".
Référence: http://www.sqlite.org/lang_keywords.html
Juste une mise à jour si quelqu'un découvre ce fil en 2019, après avoir passé des heures à chercher en ligne pourquoi cela devrait fonctionner, mais ce n'est pas le cas.
Utiliser val
fonctionne comme prévu si vous utilisez la version AndroidX (androidx.room:room-<any>:2.*
) mais pas avec l'ancien Android.Arch.persistence.room:<any>:1.1.1
et il semble que la version 2.*
n'a pas été publié sur ce dernier dépôt.
Edit: fautes de frappe