Kotlin数据类的房间数据库错误
我一直在使用Room,而且遇到阻塞问题。 我已经完成并修复了Room库中的所有编译时检查,但是现在遇到以下错误:
Entities and Pojos must have a usable public constructor. You can have an empty constructor or a constructor whose parameters match the fields (by name and type).
这在编译时出现了两次,没有证据表明这是从哪个类来的,但是我能够弄清楚(通过从数据库中删除类)这是其中的一个文件。 我假设它与主键是一个字符串,而不是一个Int(这是使用此类的两个类之一)有关,但文档中没有任何内容表明问题是什么,实际上文档显示该字符串是有效的主键。
@Entity(tableName = "inspections") data class Inspection( @SerializedName("id") var id: Int = 0, ... // Rest of code left off for brevity, found to not be related to the issue.
我已经尝试了一些事情来尝试解决这个问题。
- 删除这个类的数据属性,使其成为一个普通的POKO
- 从默认构造函数中删除变量,并将其放置到类中
- 从空的构造函数中删除Ignore(注意,这会导致一个不同的问题,
Room cannot pick a constructor since multiple constructors are suitable
– 默认构造函数的Ignore标注可以解决这个问题。)这是最困惑我的部分这说“多个构造函数是有效的”,保持它说“没有构造函数是有效的”。
更新:从我的项目中添加更多相关的代码片段。
的build.gradle
apply plugin: 'com.android.application' apply plugin: 'kotlin-android' apply plugin: 'kotlin-android-extensions' apply plugin: 'kotlin-kapt' ..... implementation 'android.arch.persistence.room:runtime:1.0.0-alpha9-1' implementation 'android.arch.persistence.room:rxjava2:1.0.0-alpha9-1' kapt 'android.arch.persistence.room:compiler:1.0.0-alpha9-1'
数据库类
@Database(entities = arrayOf(Account::class, Category::class, Inspection::class, InspectionForm::class, InspectionFormItem::class, InspectionFormsStructure::class, InspectionItemPhoto::class, InspectionItem::class, LineItem::class, LocalPhoto::class, Rating::class, Structure::class, SupervisoryZone::class, Upload::class, User::class), version = 16) @TypeConverters(Converters::class) abstract class OrangeDatabase : RoomDatabase() { abstract fun inspectionDao(): InspectionDao abstract fun localDao(): LocalDao abstract fun ratingsDao(): RatingsDao abstract fun structureZoneDao(): StructureZoneDao abstract fun userAccountDao(): UserAccountDao }
转换器
class Converters { @TypeConverter fun fromTimestamp(value: Long?): Date? { return if (value == null) Date() else Date(value) } @TypeConverter fun dateToTimestamp(date: Date?): Long? { return date?.time ?: 0 } @TypeConverter fun fromStringToArray(value: String?): Array<String>? { return value?.split(",")?.toTypedArray() ?: arrayOf() } @TypeConverter fun stringToStringArray(strings: Array<String>?): String? { return strings?.joinToString(",") ?: "" } }
另一个数据类
@Entity(tableName = "users") data class User( @PrimaryKey @SerializedName("id") var id: Int = 0, ... // Rest of code left off for brevity, found to not be related to the issue.
UserPermissions类:
data class UserPermissions( @SerializedName("id") var pid: Int = 0, ... // Rest of code left off for brevity, found to not be related to the issue.
在你的情况的问题是,如果你有可为空的值Kotlin会为每个可能的构造函数生成几个构造函数。
这意味着你必须定义一个默认构造函数,并用默认值填充它。
如果你想要另一个应该被忽略的,你应该确保使用父构造函数的所有这些参数。
例:
@Entity(tableName = "inspections") data class Inspection( @SerializedName("id") var id: Int = 0, @PrimaryKey @SerializedName("guid") var guid: String = "", @SerializedName("score") var score: Double = 0.0, @SerializedName("notification_sent_at") var notificationSentAt: Date = Date(), var wasUploaded: Boolean = false) { @Ignore constructor() : this(0, "", 0.0, Date(), false) }
在这种情况下,只有两个构造函数将在“引擎盖下”生成。 如果你有可以为空的值,你将拥有所有可能的构造函数。
例:
data class Test(var id: Int = 0, var testString: String? = null, var testBool : Boolean? = null) { constructor(0) }
生成
constructor(var id:Int) constructor() : this(0) constructor(var id:Int, var testString: String) constructor(var id:Int, var testBool: Boolean) constructor(var id:Int, var testString: String, var testBool : Boolean) // .. and so on
既然你正在寻找官方文档,你可能想看看Overloads Generation 。
经过测试你的课程完美无瑕,我发现在另一篇文章中,你必须检查你是否在你的Gradle中使用了apply plugin: 'kotlin-kapt'
。
仔细检查你的Date类是否有有效的类型转换器。 我之前写过这个问题 。
重新编码你的东西上面后,它工作得很好,通过添加一个UserPermissions类如下:
data class UserPermissions(var permissionid: String)
编辑:使用你的UserPermission类后,一切工作得很好。 请小心,如果您使用正确的导入(util.Date而不是sql.Date为例)。
另一个问题是,你使用一个古老的非常错误的房间库。
目前的版本(当写这个)是
implementation "android.arch.persistence.room:runtime:1.0.0-beta2" kapt "android.arch.persistence.room:compiler:1.0.0-beta2" implementation "android.arch.persistence.room:rxjava2:1.0.0-beta2"
我很久以前写了一个问题
尽量避免使用可为空的值,并使所有的东西都有某种默认值。 这是解决这个问题最简单的方法。
如果你真的想使用它们,那么你可以创建一个构造函数,包含所有的构造函数。
您的主键应该像下面使用注释使用站点目标一样
@field:PrimaryKey @field:SerializedName("guid") var guid: String = ""
和
@field:PrimaryKey @field:SerializedName("id") var id: Int = 0
这个问题是非常难以调试和更难以重现,但我发现这个问题。 我正在使用一个@Embedded
对象,但是结果是实际上是该对象的List
。 这给自动嵌入任务带来了麻烦,并没有一个完美的转换器可以写出来。
@SerializedName("range_choices") @Embedded var rangeChoices: List<RangeChoice>? = null,
我不得不使用@Ignore
注释,而是将这个列表的结果保存到它自己的表中,现在是新表range_choices
。
- WeakReference不在Kotlin工作
- 与java和kotlin建设的Android应用程序
- 如何检测Data class Kotlin中更改的值?
- CountdownTimer完成时如何通知Observable
- Kotlin:Sugar ORM坚持了@忽略属性
- 当我点击EditText时如何禁用键盘?
- 是否有必要知道kotlin获得AAD(Associate Android Developer)认证?
- 如何更改Kotlin属性的名称以匹配Firebase数据库上的字段
- 使用kotlin&greendao的Android Studio 3.0 Proguard将返回ClassLookupException