Search code examples
androidandroid-room

Android room persistent library - how to insert class that has a List object field


In Android room persistent library how to insert entire Model object into table which has in itself another list.

Let me show you what i mean :

@Entity(tableName = TABLE_NAME)
public class CountryModel {

    public static final String TABLE_NAME = "Countries";

    @PrimaryKey
    private int idCountry;

    private List<CountryLang> countryLang = null;

    public int getIdCountry() {
        return idCountry;
    }

    public void setIdCountry(int idCountry) {
        this.idCountry = idCountry;
    }

    public String getIsoCode() {
        return isoCode;
    }

    public void setIsoCode(String isoCode) {
        this.isoCode = isoCode;
    }

    /** 
        here i am providing a list of coutry information how to insert 
        this into db along with CountryModel at same time 
    **/
    public List<CountryLang> getCountryLang() {
        return countryLang;
    }

    public void setCountryLang(List<CountryLang> countryLang) {
        this.countryLang = countryLang;
    }
}

my DAO looks like this:

@Dao
public interface CountriesDao{

    @Query("SELECT * FROM " + CountryModel.TABLE_NAME +" WHERE isoCode =:iso_code LIMIT 1")
    LiveData<List<CountryModel>> getCountry(String iso_code);

    @Query("SELECT * FROM " + CountryModel.TABLE_NAME )
    LiveData<List<CountryModel>> getAllCountriesInfo();

    @Insert(onConflict = REPLACE)
    Long[] addCountries(List<CountryModel> countryModel);

    @Delete
    void deleteCountry(CountryModel... countryModel);

    @Update(onConflict = REPLACE)
    void updateEvent(CountryModel... countryModel);
}

When i call database.CountriesDao().addCountries(countryModel); i get the following room db compile error: Error:(58, 31) error: Cannot figure out how to save this field into database. You can consider adding a type converter for it.

should there be another table called CountryLang ? and if so how to tell room to connect them on insert statement ?

The CountryLang object itself looks like this:

public class CountryLang {


    private int idCountry;

    private int idLang;

    private String name;

    public int getIdCountry() {
        return idCountry;
    }

    public void setIdCountry(int idCountry) {
        this.idCountry = idCountry;
    }

    public int getIdLang() {
        return idLang;
    }

    public void setIdLang(int idLang) {
        this.idLang = idLang;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

}

the response looks like this:

"country_lang": [
      {
        "id_country": 2,
        "id_lang": 1,
        "name": "Austria"
      }
    ]

For every country so its not going to be more then one item here. Im comfortable desgning it for just one item in the country_lang list. So i can just make a table for country_lang and then some how link it to CountryModel. but how ? can i use foreign key ? i was hoping i did not have to use a flat file. so your saying i have to store it as json ? Is it recommended not to use room for temporary ? what to use instead ?


Solution

  • As Omkar said, you cannot. Here, I describe why you should always use @Ignore annotation according to the documentation: https://developer.android.com/training/data-storage/room/referencing-data.html#understand-no-object-references

    You will treat the Country object in a table to retrieve the data of its competence only; The Languages objects will go to another table but you can keep the same Dao:

    • Countries and Languages objects are independent, just define the primaryKey with more fields in Language entity (countryId, languageId). You can save them in series in the Repository class when the active thread is the Worker thread: two requests of inserts to the Dao.
    • To load the Countries object you have the countryId.
    • To load the related Languages objects you already have the countryId, but you will need to wait that country is loaded first, before to load the languages, so that you can set them in the parent object and return the parent object only.
    • You can probably do this in series in the Repository class when you load the country, so you will load synchronously country and then languages, as you would do at the Server side! (without ORM libraries).