1

I am using Room in Android for my database also I am using @Relation (based on this: https://developer.android.com/reference/android/arch/persistence/room/Relation.html) to fetch data from the relation entities that are related one-to-many with a ForeinKey. What I am trying to get is a List with roomAreaNames from the RoomArea Entity using @Relation. The code does not have compile errors, The issue is that I am only getting back from the @Relation is a List with size 1 (only the first object from the table) rather than the full list.

Tables:

@Entity(
    tableName = "buildings_table",
    indices = [Index("contract_id")],
    foreignKeys = [
        ForeignKey(
            entity = Contract::class,
            parentColumns = ["contract_id"],
            childColumns = ["contract_id"],
            onDelete = ForeignKey.CASCADE)]
)
data class Building(
    @PrimaryKey(autoGenerate = true) @ColumnInfo(name = "building_id")
    val buildingId: Long = 0L,

    @ColumnInfo(name = "contract_id")
    val contractId: Long,

    @ColumnInfo(name = "building_name")
    val buildingName: String)
@Entity(
    tableName = "floors_table",
    indices = [Index("building_id")],
    foreignKeys = [
        ForeignKey(
            entity = Building::class,
            parentColumns = ["building_id"],
            childColumns = ["building_id"],
            onDelete = ForeignKey.CASCADE)]
)
data class Floor(
    @PrimaryKey(autoGenerate = true) @ColumnInfo(name = "floor_id")
    val floor_id: Long = 0L,

    @ColumnInfo(name = "building_id")
    val buildingId: Long,

    @ColumnInfo(name = "level")
    val level: Int
)
@Entity(
    tableName = "rooms_area_table",
    indices = [Index("floor_id")],
    foreignKeys = [
        ForeignKey(
            entity = Floor::class,
            parentColumns = ["floor_id"],
            childColumns = ["floor_id"],
            onDelete = ForeignKey.CASCADE)]
)
data class RoomArea(
    @PrimaryKey(autoGenerate = true) @ColumnInfo(name = "room_area_id")
    val roomAreaId: Long = 0L,

    @ColumnInfo(name = "floor_id")
    val floorId: Long,

    @ColumnInfo(name = "room_area_name")
    val roomAreaName: String
)

Dao Query:

@Transaction
@Query("SELECT * FROM buildings_table WHERE contract_id = :contractId")
fun getItemsAuditBuilding(contractId: Long): LiveData<List<ItemAuditBuilding>>

Here is the @Relation (giving me a list size 1 only) i need all the roomAreas related with the buildingId

data class ItemAuditBuilding(

    @Embedded val building: Building,
    @Relation(
        parentColumn = "building_id",
        entityColumn = "room_area_id",
        entity = RoomArea::class,
        projection = ["room_area_name"]
    )
    var roomAreas: List<String>
)

Thank you.

Phantômaxx
  • 37,901
  • 21
  • 84
  • 115
  • Why are you using `@Transaction` !? – Amjad Alwareh Oct 23 '19 at 10:02
  • when I use the Query without @Transaction it does give a warning, and the outcome of the relation is the same. this is the warning: warning: `warning: The return value includes a POJO with a @Relation. It is usually desired to annotate this method with @Transaction to avoid possibility of inconsistent results between the POJO and its relations` – Marino Arias Oct 23 '19 at 10:08

2 Answers2

0

I hope this helps anyone trying to work with @relation with Room. I have based the answer to my question on the Android Dev Summit 2019. Here the link of the part where Florina speaks about room: [https://www.youtube.com/watch?v=_aJsh6P00c0]. Based on the video I have made the following changes:

I added a Junction table:

@Entity(
    primaryKeys = ["building_id", "room_area_id"],
    indices = [Index("room_area_id")]
)
data class RoomAreaWithBuilding(
    @ColumnInfo(name = "building_id")
    val buildingId: Long,
    @ColumnInfo(name = "room_area_id")
    val roomAreaId: Long
)

Then I modified the ItemAuditBuilding class

data class ItemAuditBuilding(

    @Embedded val building: Building,

    @Relation(
        parentColumn = "building_id",
        entity = RoomArea::class,
        entityColumn = "room_area_id",
        projection = ["room_area_name"],
        associateBy = Junction(RoomAreaWithBuilding::class)
    )
    val roomAreas: List<String>
)

Note: For this code to work you will need to be with Room 2.2 as associateBy is a new feature. Enjoy!!!

-1

You are trying to fetch the list of strings. I think you actually intended to do this

data class ItemAuditBuilding(
@Embedded val building: Building,
@Relation(
    parentColumn = "building_id",
    entityColumn = "room_area_id",
    entity = RoomArea::class,
    projection = ["room_area_name"]
)
var roomAreas: List<RoomArea>

)

Ruthwik Warrier
  • 187
  • 2
  • 14
  • Hi could you please explain a bit more, that class is the one i am already using. Thank you. – Marino Arias Oct 25 '19 at 04:31
  • In your code, you are mistakenly declared var roomAreas: List – Ruthwik Warrier Oct 25 '19 at 05:24
  • Oh I see what you mean, I declared as a List as I only need the column where the strings names are I do not need the whole object. For that I did add projection = ["room_area_name"]. projection allows you to do that. – Marino Arias Oct 26 '19 at 06:58