房间持久性:错误:实体和Pojos必须具有可用的公共构造函数

Leo*_*eon 46 android kotlin android-room android-architecture-components

我正在将一个项目转换为Kotlin,我正在尝试使我的模型(也是我的实体)成为一个数据类,我打算使用Moshi转换来自API的JSON响应

@Entity(tableName = "movies")
data class MovieKt(
    @PrimaryKey
    var id : Int,
    var title: String,
    var overview: String,
    var poster_path: String,
    var backdrop_path: String,
    var release_date: String,
    var vote_average: Double,
    var isFavorite: Int
)
Run Code Online (Sandbox Code Playgroud)

我无法构建应用程序导致以下错误

实体和Pojos必须具有可用的公共构造函数.您可以拥有一个空构造函数或其参数与字段匹配的构造函数(按名称和类型).找不到字段的setter.

我发现的例子离不远

关于如何解决它的想法?

Tom*_*ski 42

之前有过类似的问题.

首先,我已更新/添加apply plugin: 'kotlin-kapt'到gradle.

接下来,我使用它而不是annotationProcessorgradle:

kapt "android.arch.persistence.room:compiler:1.0.0-alpha4"

最后一件事是创建一个不可变的数据类:

@Entity(tableName = "movies")
data class MovieKt(
    @PrimaryKey
    val id : Int,
    val title: String,
    val overview: String,
    val poster_path: String,
    val backdrop_path: String,
    val release_date: String,
    val vote_average: Double,
    val isFavorite: Int
)
Run Code Online (Sandbox Code Playgroud)

更新:

当您在同一个Android模块中拥有数据库的类和数据库类时,此解决方案可以正常工作.如果您在Android库模块中有模型类,而主模块中有其余代码,则Room将无法识别它们.

  • 将`apply plugin:'kotlin-kapt'`添加到模块的`build.gradle`文件为我解决了问题,谢谢! (18认同)
  • 不使用androidx并使用'apply plugin:'kotlin-kapt' (9认同)
  • [Kotlin] 我在选择查询时遇到了这个问题,因为我忘记在 DAO 中添加返回类型 (3认同)

eva*_*oly 17

你需要指定一个辅助构造函数,如下所示:

@Entity(tableName = "movies")
data class MovieKt(
    @PrimaryKey
    var id : Int,
    var title: String,
    var overview: String,
    var poster_path: String,
    var backdrop_path: String,
    var release_date: String,
    var vote_average: Double,
    var isFavorite: Int
) {
    constructor() : this(0, "", "", "", "", "", 0.0, 0)
}    
Run Code Online (Sandbox Code Playgroud)


Thi*_*ice 17

我遇到过同样的问题。您可以将 @Ignore 字段移动到类主体。例如 :

@Entity(tableName = "movies")
data class MovieKt(
    @PrimaryKey
    var id : Int,
    var title: String
){
    //here
    @Ignore var overview: String
 }
Run Code Online (Sandbox Code Playgroud)


Fut*_*ked 12

为了扩展@evanchooly 和@daneejela 提供的答案,您需要一个辅助构造函数才能@Ignore在主构造函数中使用参数。这样 Room 仍然有一个构造函数,它可以在实例化对象时使用。根据您的示例,如果我们忽略以下字段之一:

@Entity(tableName = "movies")
data class MovieKt(
        @PrimaryKey
        var id : Int,
        var title: String,
        var overview: String,
        var poster_path: String,
        var backdrop_path: String,
        @Ignore var release_date: String,
        @Ignore var vote_average: Double,
        @Ignore var isFavorite: Int
) {
    constructor(id: Int, title: String, overview: String, poster_path: String, backdrop_path: String) {
        this(id, title, overview, poster_path, backdrop_path, "", 0.0, 0)
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 你的语法不应该是 `constructor(params) : this(params fromprimary constructor) { }` (2认同)

Ahm*_*wad 11

对我来说,我所要做的就是向数据类添加一个构造函数,并像这样发送空参数:

    @Entity(tableName = "posts")
data class JobPost(
    @Ignore
    @SerializedName("companyLogo")
    var companyLogo: String,
    @Ignore
    @SerializedName("companyName")
    var companyName: String,
    @Ignore
    @SerializedName("isAggregated")
    var isAggregated: String,
    @PrimaryKey(autoGenerate = false)
    @SerializedName("jobID")
    var jobID: String,
    @Ignore
    @SerializedName("jobTitle")
    var jobTitle: String,
    @Ignore
    @SerializedName("postedOn")
    var postedOn: String,
    @Ignore
    @SerializedName("region")
    var region: String
) {
    constructor() : this("","","","","","","")
}
Run Code Online (Sandbox Code Playgroud)


see*_*ess 11

我花了一个小时试图解决这个问题但没有成功。这就是我发现的。我忘记在我的一个查询中添加返回类型

这导致了 POJO 错误

@Query("SELECT userNote FROM CardObject WHERE identifier = :identifier")
suspend fun getUserNote(identifier: String)
Run Code Online (Sandbox Code Playgroud)

没有 POJO 错误

@Query("SELECT userNote FROM CardObject WHERE identifier = :identifier")
suspend fun getUserNote(identifier: String): String
Run Code Online (Sandbox Code Playgroud)


ste*_*ood 10

什么对我有用:

@Entity(tableName = "movies")
data class MovieKt(
    @PrimaryKey
    var id : Int? = 0,
    var title: String? = "",
    var overview: String? = "",
    var poster_path: String? = "",
    var backdrop_path: String? = "",
    var release_date: String? = "",
    var vote_average: Double? = 0.0,
    var isFavorite: Int? = 0
)
Run Code Online (Sandbox Code Playgroud)


Eri*_*k B 10

Kotlin 允许 long 作为参数名称,但是当 room 生成 java 代码时这不起作用。

  • 这是我的问题。将我的经度变量从“long”更改为“lng”修复了错误。 (2认同)

dan*_*ela 10

在您的情况下这不是问题,但对于其他情况,如果您在构造函数中具有@Ignore参数,则可能会发生此错误,即Room期望具有以下任一情况:

  • 无参数构造函数或
  • 构造函数,其中所有字段均未标有@Ignore

例如:

@Entity(tableName = "movies")
data class MovieKt(
    @PrimaryKey
    var id : Int,
    var title: String,
    @Ignore var overview: String) 
Run Code Online (Sandbox Code Playgroud)

不管用。这会:

@Entity(tableName = "movies")
data class MovieKt(
    @PrimaryKey
    var id : Int,
    var title: String) 
Run Code Online (Sandbox Code Playgroud)

  • 这是我的情况,但它没有意义,因为 @Ignore 的官方示例以相同的方式使用它:https://developer.android.com/training/data-storage/room/defining-data (3认同)
  • 因此,唯一的选择是不使用@Ignore字段? (3认同)
  • @daneejela 您也可以在主构造函数中包含“@Ignore”字段,您只需要 _some_ 构造函数,而无需 Room 可以利用的字段。详情请参阅我的回答。 (3认同)
  • 单个构造函数中的“@Ignore”是允许的(https://issuetracker.google.com/issues/70762008),带有默认值和“@JvmOverloads”注释 (2认同)

Qaz*_*han 9

今天我遇到了这个问题。我用过@Ignore,这就是我收到错误的原因。为了解决这个问题,我创建了一个辅助构造函数。所以我的代码看起来像这样:

@Entity(tableName = "profile")
data class Profile(
  @field:SerializedName("id") @PrimaryKey @ColumnInfo(name = "id") var id:Long,
  @field:SerializedName("foo") @ColumnInfo(name = "foo") var foo:String?,
  @field:SerializedName("bar") @Ignore var Bar:String?
){
   constructor(id:Long, foo:String) : this(id, foo, null)
}
Run Code Online (Sandbox Code Playgroud)

这对我有用。


小智 6

我也有这个问题,但我意识到问题是我将 @Embedded 注释添加到已经有类型转换器的属性中,因此遇到相同问题的任何人都应该仔细检查模型类的属性声明并确保 @嵌入式注释不在具有与其关联的类型转换器的属性上。


小智 5

我认为解决此问题的一个不错的选择是:

@Entity(tableName = "movies")
data class MovieKt(
    @PrimaryKey
    var id : Int = 0,
    var title: String = "",
    var overview: String = "",
    var poster_path: String = "",
    var backdrop_path: String = "",
    var release_date: String = "",
    var vote_average: Double = 0.0,
    var isFavorite: Int = 0
)
Run Code Online (Sandbox Code Playgroud)