37

I am using Room architecture component for persistence. I have created generic DAO interface to avoid boilerplate code. Room Pro Tips

But my code doesn't compile saying "Error:(21, 19) error: Type of the parameter must be a class annotated with @Entity or a collection/array of it." for the Generic class T.

interface BaseDao<T> {

@Insert(onConflict = OnConflictStrategy.REPLACE)
void insert(T... entity);

@Update
void update(T entity);

@Delete
void delete(T entity);
}

@Dao
public abstract class ReasonDao implements BaseDao<ReasonDao> {

   @Query("SELECT * from Reason")
   abstract public List<Reason> getReasons();

}

Is there anything I am missing here. It works like this here

xrnd
  • 1,273
  • 3
  • 21
  • 38

18 Answers18

56

Changed in gradle from this:

kapt "androidx.room:room-compiler:$roomVersion"

to this:

annotationProcessor "androidx.room:room-compiler:$room_version"
Boken
  • 4,825
  • 10
  • 32
  • 42
Oleg Serchenko
  • 561
  • 1
  • 3
  • 2
13

I had initially followed the method used in Kotlin, but that gives the error in Java code. Two quick changes fixed it for me

  • Change BaseDao to Abstract class
  • Added @Dao annotation to the BaseDao

Please find the code below and now it runs properly

@Dao
abstract class BaseDao<T> {

   @Insert(onConflict = OnConflictStrategy.REPLACE)
   abstract void insert(T entity);

   @Update
   abstract void update(T entity);

   @Delete
   abstract void delete(T entity);
 }

 @Dao
 public abstract class ReasonDao extends BaseDao<Reason>{

    @Query("SELECT * from Reason")
    abstract public List<Reason> getReasons();

  }
xrnd
  • 1,273
  • 3
  • 21
  • 38
  • 1
    Hello, according to my experience. When you get such error, try to comment all methods and sequentially uncomment each of them and rebuild every time. – deadfish May 17 '20 at 09:52
9

If you faced this issue in Kotlin 1.7.10+ and Room < 2.4.2, upgrading Room to 2.4.3 fixes the issue.

From Room's changelog for 2.4.3: Fixed an issue that would cause Room to not recognize suspend functions in Kotlin 1.7

This issue was due to using suspend functions for insert/delete in interfaces: https://issuetracker.google.com/issues/236612358

Shirish Kamath
  • 356
  • 4
  • 5
6

The problem was that in my build.gradle, the version of Kotlin I was using was 1.5.0

implementation "org.jetbrains.kotlin:kotlin-stdlib:1.5.0"

But as far as I understood, this version of Kotlin along with Room and coroutines doesn’t work well. Was able to resolve the issue by downgrading the Kotlin version to:

implementation "org.jetbrains.kotlin:kotlin-stdlib:1.4.32"

Solved! Thank me later

3ameration
  • 101
  • 2
  • 3
5

The reason is that you specified ReasonDao type as generic parameter instead of Reason.

Original code:

@Dao
public abstract class ReasonDao implements BaseDao<ReasonDao> {

   ...

}

Correct code:

@Dao
public abstract class ReasonDao implements BaseDao<Reason> {

   ...

}

where Reason is the type marked with @Entity annotation.

By the way, this is fixed in the accepted answer, but is not mentioned in the changelist :)

UneXp
  • 1,574
  • 2
  • 16
  • 31
4

Changed in gradle this: kapt "androidx.room:room-compiler:$roomVersion" to this: annotationProcessor "androidx.room:room-compiler:$room_version"

Doing this solution served me partially but when trying to insert a date in the database it did not work for me so try kapt "androidx.room:room-compiler:$roomVersion" and rather change room_version to the latest stable version https://developer.android.com/jetpack/androidx/releases/room#groovy ependencies {

//**
def room_version = '2.4.0'
def activityVersion = '1.4.0'
def lifecycle_version = "2.2.0"
// Room and Lifecycle dependencies
implementation "androidx.room:room-runtime:$room_version"
kapt "androidx.room:room-compiler:$room_version"
//kotlin extensions for coroutine support with room
implementation("androidx.room:room-ktx:$room_version")

//kotlin extension for coroutine support with activities
implementation "androidx.activity:activity-ktx:$activityVersion"
//**

This is how it worked for me correctly

juan
  • 49
  • 2
2

This is a version error. Try updating your room dependencies.

I changed mine from:implementation "androidx.room:room-runtime:2.2.5"

To :implementation "androidx.room:room-runtime:2.4.2"

2

remove suspend,then it will work.

@Dao
interface FoodDao {

     @Insert(onConflict = OnConflictStrategy.REPLACE)
     fun upsert(meal: Meal): Long


    @Query("SELECT * FROM food_tables")
    fun getAllFood(): LiveData<List<Meal>>


    @Delete
    fun deleteFood(meal: Meal)

}
Procrastinator
  • 2,526
  • 30
  • 27
  • 36
1

In my case I tried to save to DB non-Entity objects. Then replaced with Entity class (contains @Entity(tableName = "your_table", indices = [Index("your_key")])).

CoolMind
  • 26,736
  • 15
  • 188
  • 224
1

I believe is that you have missed to give Entity annotation to T class. For example Reason class should have @Entity and give it to ReasonDao class. Like:

@Dao public abstract class ReasonDao extends BaseDao<Reason>{}

nAkhmedov
  • 3,522
  • 4
  • 37
  • 72
1

Do not replace kapt with annotationProcessor

Try this instead

def room_version = "2.5.1"

implementation "androidx.room:room-runtime:$room_version"
annotationProcessor "androidx.room:room-compiler:$room_version"

// To use Kotlin annotation processing tool (kapt)
kapt "androidx.room:room-compiler:$room_version"

// To use Coroutine features with room
implementation "androidx.room:room-ktx:$room_version"
Neal Ratan
  • 111
  • 1
  • 3
0

What is missing here is the Data class. Generally, @Entity represents objects you want to store,

  • Room entity includes fields for each column inside the
  • table in the database
@Entity(tableName="something") data class YourData()
            
androminor
  • 322
  • 1
  • 13
0

For those who has a "Type of the parameter must be a class annotated with @Entity or a collection/array of it " error when using Kotlin in the dao , you should try using @JvmSuppressWildcards annotation on your functions. eg.

 @Query("SELECT * FROM materials")
 @JvmSuppressWildcards
 fun getAllMaterials(): LiveData<List<MaterialModel>>
Dharman
  • 30,962
  • 25
  • 85
  • 135
Gills
  • 1
  • 1
0

In my case I was trying to store a data class object into the Room Database. The error says that the parameter for Insert should be a class which has an annotation of @Entity so I created a table (entity) which has same values as data class and stored them successfully

oyeraghib
  • 878
  • 3
  • 8
  • 26
0

One small mistake I did was I did not annotate my data class with the @Entity annotation

Table declaration

@Entity // Check if you have used this annotation or not
data class fooTable(){
...
}

In DAO

@Dao
interface myDao{
  @Insert
  suspend fun addFoo(fooObj: fooTable)
  }
}

If you are trying to insert a row in a table in Room DB then the corresponding data class should be annotated with @Entity annotation

Sanket Bhangale
  • 135
  • 1
  • 7
0

Actually changing the version room matters too, like I changed my room version from 2.2.6 to 2.4.3 and it worked. if the Kotlin version is low it's better to use a lower version of the room as well if the Kotlin version is high it's better to use a higher version too.

0

In My case dependence version issue. I have upgreade dependence now working fine. so make sure dependence is according to kotlin version.

**def room_version = "2.5.1"**
implementation "androidx.room:room-runtime:$room_version"
implementation "androidx.room:room-ktx:$room_version"
kapt "androidx.room:room-compiler:$room_version"
0

I had this issue when I accidentally used vararg inside the method:

@Insert
fun insertAll(vararg postDbModels: Array<PostDbModel>)

To fix this issue I just removed vararg and using an Array of @Entity class model instead:

@Insert
fun insertAll(postDbModels: Array<PostDbModel>)
ahmnouira
  • 1,607
  • 13
  • 8