Search code examples
androidkotlinandroid-roomone-to-manyandroid-room-relation

One to many relationship in Room Database


There is an event in my project and there are timelines in this event. Each event has its own timelines. I want to list the timelines of each event with the codes I have written, but I cannot access it via the adapter.

My entities;

Event:

@Parcelize
@Entity(tableName = "event_table")
data class Event(
    @PrimaryKey(autoGenerate = true)
    val eventId: Int,
    val eventName: String,
    val eventCategory: String
): Parcelable

Timeline:

   @Parcelize
    @Entity(tableName = "timeline_table")
    data class Timeline(
        @PrimaryKey(autoGenerate = true)
        val TimeLineId: Int,
        val TimeLineAccomplish: String,
        val TimeLineDetails: String,
        val TimeLineDate: String,
        val eventCreatorId: Int
    ): Parcelable

EventAndTimeline:

data class EventAndTimeline(
    @Embedded val event: Event,
    @Relation(
        parentColumn = "eventId",
        entityColumn = "eventCreatorId"
    )
    val timeline: List<Timeline>
)

Database:

@Database(entities = [Timeline::class, Event::class], version = 1, exportSchema = false)
abstract class TimeLineDatabase: RoomDatabase() {
    abstract fun timelineDao(): TimelineDao
    abstract fun eventDao(): EventDao

    companion object{
        @Volatile
        private var INSTANCE: TimeLineDatabase? = null

        fun getDatabase(context: Context): TimeLineDatabase {
            val tempInstance = INSTANCE
            if (tempInstance != null) {
                return tempInstance
            }
            synchronized(this) {
                val instance = Room.databaseBuilder(
                    context.applicationContext,
                    TimeLineDatabase::class.java,
                    "timeline_database"
                )
                    .build()

                INSTANCE = instance
                return instance
            }
        }
    }
}

Dao:

@Dao
interface TimelineDao{
    @Transaction
    @Query("SELECT * FROM event_table")
    fun getEventsWithTimelines(): LiveData<List<EventAndTimeline>>
}

Repository:

class TimelineRepository(private val timelineDao: TimelineDao) {
   
    val readAllData: LiveData<List<EventAndTimeline>> = timelineDao.getEventsWithTimelines()
}

ViewModel:

class TimeLineViewModel(application: Application): AndroidViewModel(application) {

    val readAllData: LiveData<List<EventAndTimeline>>
  
    private val timelineRepository: TimelineRepository

    init {
        val timelineDao = TimeLineDatabase.getDatabase(application).timelineDao()
        timelineRepository = TimelineRepository(timelineDao)
        readAllData = timelineRepository.readAllData
    }

Finally: In my List adapter i want to list timelines of event. When i didnt have a relation i reach all timelines with:

holder.itemView.findViewById<TextView>(R.id.timelineDetails_txt).text 
currentItem.TimeLineDetails 

but now I can't see timelines variables(Like TimeLineDetails, TimeLineAccomplish etc.).


Solution

  • You need to write a query like the below example.

      interface UserBookDao {
            @Query(
                "SELECT user.name AS userName, book.name AS bookName " +
                "FROM user, book " +
                "WHERE user.id = book.user_id"
            )
            fun loadUserAndBookNames(): LiveData<List<UserBook>>
        
            // You can also define this class in a separate file.
            data class UserBook(val userName: String?, val bookName: String?)
        }
    

    you can check more examples in below link.

    https://developer.android.com/training/data-storage/room/relationships