07-20-2023, 03:56 PM
I've been moving into using Room, and I've run into a blocking issue. I've gone through and fixed all of the compile-time checks from the Room library, but am now encountering the following error:
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).
This appears twice at compile time with no evidence of which class this comes from, but I was able to figure out (by removing classes from the Database) that this was one of the files. I'm assuming it has something to do with the Primary Key being a string instead of an Int (this is one of two classes that uses this), but nothing in the documentation indicates what the issue would be, and in fact the documentation shows that strings are valid Primary Keys.
@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.
I've tried a few things to try and get around this.
- Remove the data attribute of this class to make it a normal POKO
- Remove the variables from the default constructor, and place them into the class
- Remove the Ignore from the empty constructor (note, this causes a different issue, `Room cannot pick a constructor since multiple constructors are suitable` - the Ignore annotation on a default constructor gets around this.) This is the part which perplexes me the most - removing this says "multiple constructors are valid", keeping it says "no constructors are valid".
Updated: Adding a few more relevant code snippets from my project.
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 class
@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
}
Converters
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(",") ?: ""
}
}
Another data class
@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 class:
data class UserPermissions(
@SerializedName("id")
var pid: Int = 0,
...
// Rest of code left off for brevity, found to not be related to the issue.
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).
This appears twice at compile time with no evidence of which class this comes from, but I was able to figure out (by removing classes from the Database) that this was one of the files. I'm assuming it has something to do with the Primary Key being a string instead of an Int (this is one of two classes that uses this), but nothing in the documentation indicates what the issue would be, and in fact the documentation shows that strings are valid Primary Keys.
@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.
I've tried a few things to try and get around this.
- Remove the data attribute of this class to make it a normal POKO
- Remove the variables from the default constructor, and place them into the class
- Remove the Ignore from the empty constructor (note, this causes a different issue, `Room cannot pick a constructor since multiple constructors are suitable` - the Ignore annotation on a default constructor gets around this.) This is the part which perplexes me the most - removing this says "multiple constructors are valid", keeping it says "no constructors are valid".
Updated: Adding a few more relevant code snippets from my project.
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 class
@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
}
Converters
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(",") ?: ""
}
}
Another data class
@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 class:
data class UserPermissions(
@SerializedName("id")
var pid: Int = 0,
...
// Rest of code left off for brevity, found to not be related to the issue.