shelll
shelll

Reputation: 3373

Room DAO with inherited interfaces

I have a DAO interface, of which I have multiple implementations and I want one of them to be a Room implementation (Kotlin):

interface BaseDao {
    fun getAll(): Single<List<SomeData>>
    fun insert(data: List<SomeData>)
}

and my Room (RxRoom) interface:

@Dao
interface RxRoomBaseDao: BaseDao {
    @Query("SELECT * FROM some_data")
    override fun getAll(): Single<List<SomeData>>

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    override fun insert(data: List<SomeData>)
}

It looks like the Room compiler tries to compile the BaseDao instead of the RxRoomBaseDao and complains error: Dao class must be annotated with @Dao and for both methods error: A DAO method can be annotated with only one of the following:Insert,Delete,Query,Update.

I have also tried an abstract class for the RxRoomBaseDao with the same result.

Is this a known bug or limitation of the Room compiler? How can I achieve what I want without polluting my BaseDao with Room's annotations?

Upvotes: 14

Views: 6139

Answers (3)

Homayoon Ahmadi
Homayoon Ahmadi

Reputation: 2833

my BaseDao interface:

@Dao
interface BaseDao<T> {

    /**
     * Insert an entity into the table.
     *
     * @param entity The entity to insert.
     */
    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun insert(entity: T)

    /**
     * Insert multiple entities into the table.
     *
     * @param entities The list of entities to insert.
     */
    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun insertAll(entities: List<T>)

    /**
     * Update an entity in the table.
     *
     * @param entity The entity to update.
     */
    @Update
    suspend fun update(entity: T)

    /**
     * Delete an entity from the table.
     *
     * @param entity The entity to delete.
     */
    @Delete
    suspend fun delete(entity: T)
}

you can use it like this:

@Dao
interface PointDao : BaseDao<Point> {

   // custom queries goes here...

    @Query("SELECT * FROM Point")
    fun getAll(): Flow<List<Point>>
}

Upvotes: 0

kip2
kip2

Reputation: 6883

It seems OP has since moved on from Room, but fwiw, it's possible to use generics to solve this problem:

interface BaseDao<T> {
    @Insert
    fun insert(vararg obj: T)
}
@Dao
abstract class DataDao : BaseDao<Data>() {
    @Query("SELECT * FROM Data")
    abstract fun getData(): List<Data>
}

Check out the "Use DAO's inheritance capability" section in this Official Room blog post

Upvotes: 10

Ecnill
Ecnill

Reputation: 41

Create your dao as an abstract class:

@Dao
public abstract class EntityDao implements Base {

   @Override
   @Query("SELECT * FROM " + Entity.TABLE_NAME)
   public abstract Flowable<List<Entity>> getEntities();
}

interface Base {
   Flowable<List<Entity>> getEntities();
}

Upvotes: 0

Related Questions