Search code examples
androidkotlinmobileandroid-room

Abstract database methods must return a @Dao annotated class or interface


I think this topic already existed. But, since we have a new version of room database, it will be helpful to me to understand better. So, I am implementing a room database with the version 2.3.0 but I am getting lot of errors:

  1. Type of the parameter must be a class annotated with @Entity or a collection/array of it. kotlin.coroutines.Continuation<? super kotlin.Unit> continuation);
  2. Not sure how to handle insert method's return type. public abstract java.lang.Object insertStudent(@org.jetbrains.annotations.NotNull()
  3. Abstract database methods must return a @Dao annotated class or interface. public abstract void setConnectDatabaseDao(@org.jetbrains.annotations.NotNull()

Like said here, I added ktx extension to support suspendable meethods in Dao. But it's still giving me these errors. Here are my code : app build gradle

plugins {
    id 'com.android.application'
    id 'kotlin-android-extensions'
    id 'kotlin-android'
    //id 'kotlin-parcelize'
}
apply plugin: 'kotlin-kapt'
...
//room data base
    implementation "androidx.room:room-runtime:$room_version"
    annotationProcessor "androidx.room:room-compiler:$room_version"
    implementation "androidx.lifecycle:lifecycle-extensions:2.2.0"
    kapt "androidx.lifecycle:lifecycle-compiler:2.4.0"
    kapt "androidx.room:room-compiler:$room_version"
    implementation "androidx.room:room-ktx:$room_version"

    // optional - RxJava2 support for Room
    implementation "androidx.room:room-rxjava2:$room_version"


    // optional - Guava support for Room, including Optional and ListenableFuture
    implementation "androidx.room:room-guava:$room_version"

    // optional - Test helpers
    testImplementation "androidx.room:room-testing:$room_version"

    // optional - Paging 3 Integration
    implementation "androidx.room:room-paging:2.4.0-rc01"

Database

@Database(entities = [Skill::class, Student::class], version = 1, exportSchema = false)
abstract class ConnectDatabase():RoomDatabase() {

    abstract var connectDatabaseDao:ConnectDatabaseDao
    companion object{
        @Volatile
        var INSTANCE:ConnectDatabase? = null
        fun getInstance(context:Context): ConnectDatabase {
            synchronized(this) {
                var instance = INSTANCE
                if (instance == null) {
                    instance = Room.databaseBuilder(
                        context,
                        ConnectDatabase::class.java,
                        "connect_database"
                    )
                        .fallbackToDestructiveMigration()
                        .build()
                    INSTANCE = instance
                }
                return instance
            }
        }
    }

}

Dao


@Dao
interface ConnectDatabaseDao {
    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun insertStudent(student: Student)

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun insertSkill (skill: Skill)

    @Delete
    suspend fun deleteStudent(student: Student)

    @Delete
    suspend fun deleteSkill(skill: Skill)

    @Query("SELECT * FROM student WHERE id = :id")
    suspend fun getStudent(id:Long):Student?

    @Query("SELECT * FROM skill WHERE id = :id")
    suspend fun getSkill(id:Long):Skill?

    @Query("SELECT * FROM student")
    fun getAllStudent():LiveData<List<Student>?>

    @Query("SELECT * FROM skill")
    fun getAllSkill():LiveData<List<Skill>?>

}

Data class

@Parcelize
@Entity(tableName = "student",
    foreignKeys = arrayOf(
        ForeignKey(entity = Skill::class,
            parentColumns = arrayOf("id"),
            childColumns = arrayOf("id_skill"),
            onDelete = ForeignKey.CASCADE
            )
        )
)
data class Student (
        @PrimaryKey(autoGenerate = true)
        @ColumnInfo(name = "id")
        val id: Long,

        @ColumnInfo(name = "name")
        val name: String,

        @ColumnInfo(name= "email")
        val email: String,

        @ColumnInfo(name = "id_skill")
        val idSkill: Long
        ):Parcelable
@Parcelize
@Entity(tableName = "skill")
data class Skill (
    @PrimaryKey(autoGenerate = true)
    @ColumnInfo(name = "id")
    val id: Long,

    @ColumnInfo(name = "item")
    val item:String
): Parcelable

Do someone knows what create the problem please ?


Solution

  • One issue is as per the title so :-

    abstract var connectDatabaseDao:ConnectDatabaseDao
    

    should instead be

    abstract fun getConnectDatabaseDao(): ConnectDatabaseDao
    

    The other issues can be overcome by using SDK 30 and removing the suspend from suspend fun .... and having just fun .... when using 2.3.0.

    e.g.

    enter image description here