I get this common Error:
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).
- java.util.List
I browsed across the answers and they mostly suggest that Room needs default values or empty constructors. However, providing these did not solve the issue.
Neither was the issue solved by putting @Ignore Annotations on the non-empty constructors.
There were also suggestions that @embedded annotation is broken, but that particular issue was from 2017 and I am using the current version. I really do need @Embedded and not @Relation, because Relations tend to ignore where-conditions.
This is the DAO query (one-to-many):
@Transaction
@Query("Select Distinct Category.* " +
"from Category join EntryStandard on Category.CID = EntryStandard.CategoryID " +
"where date(EntryStandard.EntryDate) " +
"between date( :paramStart) and date( :paramEnd) " +
"order by lower( Category.Name ) asc")
open fun getCatViewWithItemList(paramStart: LocalDateTime, paramEnd: LocalDateTime): MutableList<CatsWithItems>
This is the class with the embedded list:
class CatsWithItems(sName: String,
iHeaduid : String?,
sHeadName : String?,
@Embedded
var Cats: List<ItemS>) : Cat(
UUID.randomUUID().toString(),
iHeaduid,
sHeadName,
sName
)
{
constructor(): this("", "", "", ArrayList())
}
This is the parent object:
@Entity(tableName = "Category")
open class Cat(
@PrimaryKey @ColumnInfo(name = "CID")
var uid: String = UUID.randomUUID().toString(),
@ColumnInfo(name = "HeadID")
var iHeaduid: String?,
@ColumnInfo(name = "HeadName")
var sHeadName: String?,
@ColumnInfo(name = "Name")
var sName: String
)
: TreeItemInterface {
// empty constructor to avoid error
constructor() : this("","","","")
// secondary constructor
constructor (sNameP: String, oHeadCatP: Cat?): this(
UUID.randomUUID().toString(),
oHeadCatP?.uid,
oHeadCatP?.sName,
sNameP
)
// secondary constructor
constructor (name: String, sHeadUID : String?, sHeadName : String?): this(
UUID.randomUUID().toString(),
sHeadUID,
sHeadName,
name
)
fun CreateSubCat(sParamP: String?): Cat? {
return sParamP?.let { Cat(it, this) }
}
fun NoParent(): Boolean {
return iHeaduid.isNullOrEmpty()
}
@Ignore
override fun getNameForView(): String {
return sName
}
override fun getUIDOfDBItem(): String {
return uid
}
override fun getListItemType(): Int {
return ListItemType.CategoryPlain
}
}
the child object:
@Entity(tableName = "EntryStandard")
data class ItemS(
@PrimaryKey @ColumnInfo(name = "SID")
val uid: String = UUID.randomUUID().toString(),
//TypeConverter turns this into long
@ColumnInfo(name = "Amount")
var decAmount: BigDecimal,
@ColumnInfo(name = "CategoryID")
val iCatID: String?,
) : TreeItemInterface, SubNode(LocalDateTime.now()) {
// empty constructor to avoid error
constructor() : this("", BigDecimal.ZERO,"")
// secondary constructor
constructor(decAmountP: BigDecimal, oCatIDP: String?) : this (
UUID.randomUUID().toString(),
decAmountP.setScale(2, BigDecimal.ROUND_HALF_DOWN),
oCatIDP
)
@Ignore
fun getAmountScaled(): BigDecimal {
return decAmount.setScale(2, BigDecimal.ROUND_HALF_DOWN)
}
@Ignore
override fun getNameForView(): String {
return this.getAmountScaled().toString()
}
@Ignore
override fun getUIDOfDBItem(): String {
return uid
}
override fun getListItemType(): Int {
return if (this.iCatID.isNullOrEmpty()) ListItemType.UncategorizedEntry
else ListItemType.Entry
}
}
thanks for reading!