96

我正在将一个项目转换为 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
)

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

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

我发现的例子离这个不远

关于如何解决它的想法?

4

30 回答 30

51

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

  • 无参数构造函数或
  • 构造函数的所有字段都没有用@Ignore 标记

例如:

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

不管用。这将:

@Entity(tableName = "movies")
data class MovieKt(
    @PrimaryKey
    var id : Int,
    var title: String) 
于 2019-07-12T19:48:44.947 回答
43

之前有过类似的问题。

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

接下来,我使用它而不是annotationProcessor在 gradle 中:

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
)

更新:

当您在同一个 Android 模块中有模型类和数据库类时,此解决方案有效。如果您在 Android 库模块中有模型类,而主模块中有其余代码,Room 将无法识别它们。

于 2017-07-20T07:46:04.000 回答
28

你需要像这样指定一个辅助构造函数:

@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)
}    
于 2017-06-11T20:06:42.620 回答
24

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

@Entity(tableName = "movies")
data class MovieKt(
    @PrimaryKey
    var id : Int,
    var title: String
){
    //here
    @Ignore var overview: String
 }
于 2019-12-27T09:27:25.417 回答
16

要扩展@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)
    
}
于 2019-12-11T18:39:25.240 回答
14

什么对我有用:

@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
)
于 2017-06-22T17:49:05.073 回答
12

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

于 2018-09-11T22:23:24.257 回答
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("","","","","","","")
}
于 2018-11-03T17:45:45.237 回答
10

今天我遇到了这个问题。我用过@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)
}

这对我有用。

于 2020-06-20T11:44:01.933 回答
7

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

于 2018-07-29T02:14:59.607 回答
4

我认为解决它的一个好选择是:

@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
)
于 2017-06-16T01:14:47.490 回答
4

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

这导致了 POJO 错误

@Query("SELECT userNote FROM CardObject WHERE identifier = :identifier")
suspend fun getUserNote(identifier: String)

没有 POJO 错误

@Query("SELECT userNote FROM CardObject WHERE identifier = :identifier")
suspend fun getUserNote(identifier: String): String
于 2021-05-16T13:37:05.427 回答
3

对我来说,我在 kotlin 的数据(实体)类中使用 'lat' 和 'long' 作为变量名,因此重命名为纬度和经度就可以了。

不工作:

@Entity(tableName = "table_User")
data class User(@PrimaryKey var userId : Int, @ColumnInfo(name = "first_name") 
var firstName: String
            , @ColumnInfo(name = "last_name") var lastName: String
            , @ColumnInfo(name = "password") var password: String
            , @ColumnInfo(name = "dob") var dob: Long
            , @ColumnInfo(name = "address") var address: String
            , @ColumnInfo(name = "lat") var latitude: Double
            , @ColumnInfo(name = "long") var longitude: Double) {

}

在职的:

@Entity(tableName = "table_User")
data class User(@PrimaryKey var userId : Int, @ColumnInfo(name = "first_name") 
var firstName: String
            , @ColumnInfo(name = "last_name") var lastName: String
            , @ColumnInfo(name = "password") var password: String
            , @ColumnInfo(name = "dob") var dob: Long
            , @ColumnInfo(name = "address") var address: String
            , @ColumnInfo(name = "latitude") var latitude: Double
            , @ColumnInfo(name = "longitude") var longitude: Double) {

}
于 2019-05-11T13:08:32.890 回答
2

就像 Room 文档中所说的那样,您需要创建一个空的 public constructor。同时,如果要声明其他自定义构造函数,则必须添加@Ignore注解。

@Entity
public class CartItem {
    @PrimaryKey
    public int product_id;
    public int qty;

    public CartItem() {
    }

    @Ignore
    public CartItem(int product_id, int count) {
        this.product_id = product_id;
        this.qty = count;
    }
}
于 2020-03-19T10:40:52.440 回答
2

我遇到了一个实体的问题(所有字段都已正确初始化var,就像这里的很多答案都建议的那样),其中包括一个相关的、非原始项目的列表,比如这个SO 问题中的 OP。例如:

@Entity(tableName = "fruits")
data class CachedFruitEntity(
        @PrimaryKey var id: Long = 0L,
        @Embedded(prefix = "buyer_") var buyerEntity: CachedBuyerEntity? = null
        @TypeConverters(VendorsConverter::class)
        var vendorEntities: List<CachedVendorEntity?> = listOf()))

也就是说,它有一个嵌入式字段,我花了一段时间才意识到我真正需要的是供应商实体列表的类型转换器(编译器没有抛出通常的所以我的解决方案与这个答案Error:(58, 31) error: Cannot figure out how to save this field into database. You can consider adding a type converter for it.非常相似

这个google architecture components github thread有更多关于这个误导性错误的信息,但不确定问题是否已经修复。

于 2018-05-25T18:40:54.790 回答
1

只需将以下注释添加到导致错误的任何构造函数并添加一个新的空白构造函数。

@忽视

于 2019-01-09T08:45:07.503 回答
1

不要使用数据类,而是使用普通类。这个方法可以解决问题

于 2019-02-06T15:47:56.060 回答
1

https://issuetracker.google.com/issues/62851733

我发现这是@Relation 的投影错误!不是 Kotlin 语言问题。基于 google GithubBrowserSample java 也发生错误,但错误消息不同。

下面是我的科特林代码:

data class UserWithCommunities(
        @Embedded
        var user: User = User(0, null),

        @Relation(parentColumn = "id",
                entityColumn = "users_id",
                entity = CommunityUsers::class,
                projection = arrayOf("communities_id")) // delete this line.
        var communityIds: List<Int> = emptyList()
)

正确的:

data class UserWithCommunities(
        @Embedded
        var user: User = User(0, null),

        @Relation(parentColumn = "id",
                entityColumn = "users_id",
                entity = CommunityUsers::class)
        var communityList: List<CommunityUsers> = emptyList()
)
于 2017-09-01T08:20:48.987 回答
1

Kotlin 插件不获取 annotationProcessor 依赖项,因此请使用最新版本的 Kotlin 注释处理器 - 将此行放在模块级别 build.gradle文件的顶部

apply plugin: 'kotlin-kapt'

喜欢

apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt'  // add this line

android {
    compileSdkVersion 28
    defaultConfig {
      ........
    }
}

不要忘记相应地更改 compileSdkVersion。

于 2020-05-29T11:25:50.043 回答
1

同样的错误,更奇怪的解决方案:不要Maybe<Cursor>在你的 Dao 上使用响应式返回光标。Flowable, Single,Observable也没有工作。

只需硬着头皮在 Dao 请求之外进行响应式调用。前:

@Dao
interface MyDao{
    @Query("SELECT * FROM mydao")
    fun getCursorAll(): Flowable<Cursor>
}

后:

@Dao
interface MyDao{
    @Query("SELECT * FROM mydao")
    fun getCursorAll(): Cursor
}

元:

Android Studio 3.2
Build #AI-181.5540.7.32.5014246, built on September 17, 2018
JRE: 1.8.0_152-release-1136-b06 x86_64
JVM: OpenJDK 64-Bit Server VM by JetBrains s.r.o
macOS 10.12.6
于 2018-12-13T21:35:05.650 回答
1

对于这个问题,我遇到了同样的问题。

将依赖项替换为官方文档Room中最新的依赖项

于 2021-10-16T07:33:43.960 回答
1

原来是库上的一个错误 https://github.com/googlesamples/android-architecture-components/issues/49

于 2017-06-12T09:27:06.497 回答
1

在 2.1.0-alpha6 中,它被证明是 Dao 中的无效返回类型。按预期修复返回类型修复了它。

于 2019-04-09T23:39:09.677 回答
1

我遇到了同样的问题,原因是我在 dao 中通过查询获得的数据类型不等于我返回的数据类型。

我的数据库中的 id 类型是 String,我将 dao 更改为:

@Query("SELECT id FROM content_table")
fun getIds(): Flow<List<Int>>

至 :

@Query("SELECT id FROM content_table")
fun getIds(): Flow<List<String>>
于 2021-05-17T18:17:30.163 回答
0

就我而言,我有 @Ignore Tags 和 'kotlin-kapt' 插件,但在将kotlin更新到1.5.0版本后仍然开始发生这种情况。

我最终将我的房间库从版本2.2.5更新到了2.3.0,问题得到了解决。

于 2021-05-26T10:57:27.053 回答
0

确保room数据库column名称和字段名称constructor相同

于 2021-02-09T08:12:11.540 回答
0

房间数据库Entity所述:

每个实体必须要么有一个无参数构造函数,要么有一个参数匹配字段(基于类型和名称)的构造函数。

因此,添加一个空构造函数并用注释您的参数化构造函数@Ignore将解决您的问题。一个例子:

public class POJO {

    long id;

    String firstName;

    @Ignore
    String lastName;

    public POJO() {
    }

    @Ignore
    public POJO(String firstName, String lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }

    // getters and setters
    // ...

}
于 2019-01-09T09:53:01.517 回答
0

另一个问题

@Entity
data class SomeEnity(
    @PrimaryKey(autoGenerate = true)
    val id: Long = 0,
    val filed: SomeClass
)

**inline** class SomeClass

考虑删除内联

于 2022-01-14T14:13:09.890 回答
-1

就我而言,我没有在其中一个 Dao 查询中返回类型,希望它可以帮助其他人谢谢

于 2020-07-22T06:12:58.513 回答
-2

对于实现自动生成的 FutureShocked 答案的变体:

@Entity(tableName = "movies")
data class MovieKt(
        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
) {
@PrimaryKey(autoGenerate = true) var id : Int = 0

    constructor(title: String, overview: String, poster_path: String, backdrop_path: String) {
        this(id, title, overview, poster_path, backdrop_path, "", 0.0, 0)
    }
}
于 2020-01-21T18:34:27.890 回答