Boycott A.I.
Boycott A.I.

Reputation: 18871

How to embed a Room entity that isn't directly related?

I have three basic entities that represent the tables in my Room database: Country, State and City.

To embed a list of cities within a state, I've created a POJO, called StateWithCities:

package org.example.roomtest;

import java.util.List;
import androidx.room.Embedded;
import androidx.room.Relation;

public class StateWithCities {

    @Embedded
    public State state;

    @Relation(
            parentColumn = "_id", // This is the `states`.`_id` column.
            entityColumn = "state_id" // This is the `cities`.`state_id` column.
    )
    public List<City> cities;
}

which I can then return from a query in my StateDao interface:

@Query("SELECT * FROM `states`")
LiveData<List<StateWithCities>> getAllStatesWithCities();

However, I would now like to create a query in my CountryDao interface that can return the cities associated with a country.

(Countries and cities are related via the states table. So, as you'd expect, cities.state_id relates to states._id. And states.country_id relates to countries._id.)

So I have created a CountryWithStatesWithCities POJO:

package org.example.roomtest;

import java.util.List;
import androidx.room.Embedded;
import androidx.room.Relation;

public class CountryWithStatesWithCities {

    @Embedded
    public Country country;

    @Relation(
            parentColumn = "_id", // This is the `country`.`_id` column.
            entityColumn = "country_id" // This is the `states`.`country_id` column.
    )
    public List<StateWithCities> stateWithCities;
}

At this point, everything compiles fine. But when I add this query to CountryDao:

@Query("SELECT * FROM `countries`")
LiveData<List<CountryWithStatesWithCities>> getAllCountriesWithStatesWithCities();

I get these compile errors that refer to my two classes, above:

> ...StateWithCities.java:7: error: The class must be either @Entity or @DatabaseView.
> public class StateWithCities {
>        ^

and

> ...CountryWithStatesWithCities.java:16: error: Cannot find the child entity column `country_id` in org.team_love.shapethefuture.roomtest.StateWithCities. Options: 
>     public List<StateWithCities> stateWithCities;
>                                  ^

These errors seem to be telling me that my CountryDao interface needs to be referencing Entities (or DatabaseViews) rather than POJOs. So, what is the correct approach to solving my requirement: How to embed a Room entity that isn't directly related?

Upvotes: 4

Views: 641

Answers (1)

sergiy tykhonov
sergiy tykhonov

Reputation: 5103

You need to set your entity class explicitly describing CountryWithStatesWithCities, since Room has a problem to infer it from the context:

public class CountryWithStatesWithCities {

    @Embedded
    public Country country;

    @Relation(
            entity = State.class, <- this should be added explicitly
            parentColumn = "_id", // This is the `country`.`_id` column.
            entityColumn = "country_id" // This is the `states`.`country_id` column.
    )
    public List<StateWithCities> stateWithCities;
}

Upvotes: 5

Related Questions