KamielDev
KamielDev

Reputation: 569

Why did I get the error 'Entities and POJOs must have a usable public constructor' when adding a (faulty) Room database query to my DAO?

I was recently working on an Android app and ran into the 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) when adding Query's to my Room database repository class.

However, this took me quite a while to spot, because the error I got when building was, to my knowledge, quite unrelated. When searching SO for this question, I found a lot of answers which list something along the likes of 'Make sure you annotate your variables with @ColumnInfo' or 'Move your @Ignore tags to the body of the function' or 'Make an empty constructor like it says' but none of these were applicable to me or fixed the problem.

The weird thing was, my App ran fine if I just removed these three queries from my program, so it couldn't have anything to do with the constructor message.

Eventually, I noticed that my database Query was wrong (see comment in below code). This took me much longer than it should have though, since I had no clue my Query was causing a seemingly unrelated buildlog error.

I'm mostly posting this question here so that someone else might find it if they find themselves in a similar situation (ENSURE YOUR QUERIES ARE CORRECT!!), but I am also wondering if I'm understanding this error message wrong, or if it's actually a faulty error message.

Can someone explain to me why a faulty quert would result into said error message?

DAO containing faulty queries:

@Dao
interface GameItemDAO {

    @Query("SELECT * FROM gameItemTable")
    suspend fun getAllGameItems(): List<GameItem>

    @Insert
    suspend fun insertGameItem(gameItem: GameItem)

    @Delete
    suspend fun deleteGameItem(gameItem: GameItem)

    @Query("DELETE FROM gameItemTable")
    suspend fun deleteAllGameItems()

    @Query("SELECT * FROM gameItemTable ORDER BY ID DESC LIMIT 1")
    suspend fun getLastGameItem(): GameItem?


    // These functions were faulty, and should have listed SELECT COUNT (*) FROM...
    @Query("SELECT * FROM gameItemTable WHERE OUTCOME=0")
    suspend fun getWinCount(): Int

    @Query("SELECT * FROM gameItemTable WHERE OUTCOME=1")
    suspend fun getLossCount(): Int

    @Query("SELECT * FROM gameItemTable WHERE OUTCOME=2")
    suspend fun getDrawCount(): Int
}

@Entity class:

@Entity(tableName = "gameItemTable")
data class GameItem(

        @ColumnInfo(name = "date")
        var date: Date,

        @ColumnInfo(name = "moveComputer")
        var moveComputer: MoveType,

        @ColumnInfo(name = "movePlayer")
        var movePlayer: MoveType,

        @ColumnInfo(name = "outcome")
        var outcome: OutcomeType,

        @PrimaryKey(autoGenerate = true)
        @ColumnInfo(name = "id")
        var id: Long? = null
)

Upvotes: 0

Views: 79

Answers (1)

MSDarwish
MSDarwish

Reputation: 89

The error message is quite correct. Please note that when the return type of a query is not a collection/array/list of some type, Room will return the first item found, though it will retrieve all the data internally so it's not a good practice to depend on that behavior.

In your faulty case, you're asking Room to fetch * which means that it is expecting to return an object of a type with properties matching the 5 columns of the table. Also, it needs to know how to build it, either using a constructor with parameters matching the five columns or an empty constructor with setters for the five columns. Of course, Int doesn't match.

Upvotes: 1

Related Questions