找不到字段的setter - 使用Kotlin和Room数据库

gsb*_*gsb 52 android kotlin android-room

我正在与Room持久性库集成.我在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
)
Run Code Online (Sandbox Code Playgroud)

这些@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.
Run Code Online (Sandbox Code Playgroud)

我也试过提供一个默认的构造函数:

@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, "", "", "")
}
Run Code Online (Sandbox Code Playgroud)

但这并不奏效.需要注意的是,如果我将这个Kotlin类转换为带有getter和setter的Java类,它就可以工作.任何帮助表示赞赏!

Jan*_*ert 137

由于您的字段已标记val,因此它们实际上是最终的,并且没有setter字段.

尝试切换出valvar.您可能还需要初始化字段.

@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 = ""
)
Run Code Online (Sandbox Code Playgroud)

  • 答案意味着'不要使用Room,它会强迫你写错代码',对吗? (6认同)
  • 请注意,数据类中的var使用会导致有效的不变性损失。 (3认同)

AJa*_*Jay 25

嘿,我不知道大家知道或没有,但你不能拥有这是从起始列isRoom.例如,你不能有这样的

   @Entity(tableName = "user")
   data class User (
        @PrimaryKey var id: Long? = null,
        var userName: String = "",
        var isConnectedToFB: Boolean = false,
)
Run Code Online (Sandbox Code Playgroud)

  • 就我而言,“is”前缀不适用于字段名称。但是“is”前缀适用于布尔类型字段。 (2认同)
  • 它与Java一起使用,但与Kotlin不一起使用 (2认同)

小智 10

只需使变量可变,对于 Kotlin 更改valvarprivate,或者对于 Java 更改为 public


Qam*_*mar 7

Room db 库java 代码生成存在问题。

我正在使用可选字段isFavorite。它给了我同样的错误,然后我将字段名称更改为favorite然后编译。

之前 var isFavorite: Int? = 0, 更改后工作正常 var favorite: Int? = 0, 谢谢


Coo*_*ind 7

根据/sf/answers/3272766311/如果你有一个自动生成的主键,你应该这样写:

@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
}
Run Code Online (Sandbox Code Playgroud)

请注意,@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)
Run Code Online (Sandbox Code Playgroud)

更新

我仍然不使用 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::

在此处输入图片说明

然后我将 anid从主体移动到构造函数。在 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
Run Code Online (Sandbox Code Playgroud)


liv*_*ove 6

Had this error in Java.

You cannot have a column starting with is or is_ in Java.

Try renaming the column.

Another solution:

You either have to pass the field in the constructor and initialize it with the constructor argument, or create a setter for it.

Example:

public MyEntity(String name, ...) {
   this.name = name;
   ...
}

public void setName(String name) {
    this.name = name;
}
Run Code Online (Sandbox Code Playgroud)


小智 6

如果您的列以 Is 开头,则会引发此错误:

@ColumnInfo(name = "IsHandicapLeague")
    @NonNull
    var isHandicapLeague: String = "Y"
Run Code Online (Sandbox Code Playgroud)

添加默认的set()函数来消除

fun setIsHandicapLeague(flag:String) {
    isHandicapLeague = flag
}
Run Code Online (Sandbox Code Playgroud)


Tou*_*che 6

解决此问题的正确方法是简单地更新到Room v2.4.3 或更高版本。

解决方法

如果您运行的是旧版本的 Room(使用旧版本的kotlinx-metadata-jvm库且不理解 1.5.x 元数据),一个简单的解决方法是将以下行添加到您的build.gradle

kapt "org.jetbrains.kotlinx:kotlinx-metadata-jvm:0.5.0"
Run Code Online (Sandbox Code Playgroud)

来源:https://youtrack.jetbrains.com/issue/KT-45883/KAPT-Cannot-find-setter-for-field-compiling-projects-with-Room-db-breaks-using-150-M2


Mil*_*lan 5

如果@Ignore数据类构造函数中有字段,则需要将其移动到类主体,如下所示:

@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?
}
Run Code Online (Sandbox Code Playgroud)

所有荣誉都归于GitHub 上的marianpercahttps : //github.com/android/architecture-components-samples/issues/421#issuecomment-442763610