Search code examples
javaandroidentitypersistencedao

Implementing a base dao, I get error Type of the parameter must be a class annotated with @Entity or a collection/array of it


I am struggeling with creating a base DAO in Java using Room in Android. There are several posts out there but not one solves the error I get.

This is the error I get at compile time:

error: Type of the parameter must be a class annotated with @Entity or a collection/array of it.

This is my entity / model class:

@Entity (tableName = "user")
public class User {

    @PrimaryKey
    @ColumnInfo (name = "user_id")
    private int userId;
    @ColumnInfo (name = "lastname")
    private String lastName;
    @ColumnInfo (name = "firstname")
    private String firstName;

    public User(int userId, String lastName, String firstName) {
        this.userId = userId;
        this.lastName = lastName;
        this.firstName = firstName;
    }

    public int getUserId() {
        return userId;
    }

    public void setUserId(int userId) {
        this.userId = userId;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }
}

This is my base DAO:

@Dao
public abstract class BaseDao<T> {

    @Insert
    public abstract long insert(T object);      // error here

    @Insert
    public abstract long[] insertAll(List<T> object);    // error here

    @Update
    public abstract int update(T object);   // error here

    @Update
    public abstract int updateAll(List<T> object);   // error here

    @Delete
    public abstract int delete(T object);   // error here

    @Delete
    public abstract int deleteAll(List<T> object);    // error here

}

This is my User DAO:


@Dao
public abstract class UserDao extends BaseDao<User> {

    @Query ("select * from user")
    public abstract LiveData<List<User>> getAll();

    @Query("delete from user")
    public abstract int deleteAll();

}

I get six compilation errors of the same type. That ist the number of functions in my base DAO. Of course generic type T is not annotated with @Entity, but how to deal with that fact?

What I tried to solve this:

  • Read all posts about this topic carefully over days. Most posts use Kotlin, and I believe that it works for Kotlin, but I use Java.
  • Tried to implement the Base DAO as an interface or abstract class
  • Tried to annotate / not annotate the base DAO with @Dao (as mentioned in some posts)
  • Tried to create a Base Entity annotated with @Entity and have my model classes extend that like so:
@Entity
public class BaseEntity { ... }    // Base entity annotated with @Entity

public class User extends BaseEntity { ... }    // subclass the model class from BaseEntity

public abstract class BaseDao<T extends BaseEntity> { ...}    // type parameterize BaseDao with base type BaseEntity

public abstract class UserDao extends BaseDao<User> { ...}    // type T should now be an descendant of BaseEntity which is an @Entity 

None of this worked for me!

Some of the posts tell, that it has worked for them this way, but not for me. I hope someone can tell me what I'm doing wrong!


Solution

  • Finally I found the error!

    Among my model classes I have one model, that is just a DTO for a joined query result.

    public class SessionAndUser {
    
        @Embedded
        private Session session;
    
        @Relation(parentColumn = "user_id", entityColumn = "user_id")
        private User user;
    }
    

    The DAO implementation looks like this:

    
    @Dao
    public abstract class SessionAndUserDao {   //extends BaseDao<SessionAndUser> { <-- this caused the error
    
        @Transaction
        @Query("select * from session")
        public abstract LiveData<List<SessionandUser>> getAll();
    
    }
    

    Because of SessionAndUser is not in the database it must not be annotated with @Entity.

    The error was, that I extended the DAO from my base DAO. So the solution for me was, to just create the dao without extending the base DAO (in fact it does not need the functionality of the base DAO).

    After figuring out that, I could see that every kind of tested implementations (using interfaces or abstract classes, using Java or Kotlin) worked as expected.