web-dev-qa-db-fra.com

Impossible de trouver un paramètre pour le champ - utilisation de la base de données Kotlin with Room

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!

49
gsb

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 = ""
)
126

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,
)
21
AJay

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

4
Qamar

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:

enter image description here

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
3
CoolMind

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
3
triad

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;
}
2
live-love

Si vous voulez que l'immutabilité de val soit disponible pour votre entité, c'est possible.

  1. Vous devez mettre à jour vers la salle AndroidX version actuelle .
  2. Vérifiez le connexe problème ici il est marqué comme ne sera pas résolu
  3. Maintenant, ils ont publié un correctif lié au problème avec version 2.0.0-beta01
  4. Maintenant, vous pouvez utiliser _ immuable 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

1
mochadwi

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

1
dgngulcan

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

1
Jibbo