Basically, there are two things I don't understand: objects with objects and objects with lists of objects
Say I receive a list of objects from the server. Each of them looks like this:
@Entity
public class BigObject {
@PrimaryKey
private int id;
private User user;
private List<SmallObject> smallObjects;
}
with these two objects as fields:
@Entity
public class User {
@PrimaryKey
private int id;
private String name;
@TypeConverters(GenderConverter.class)
public MyEnums.Gender gender;
}
@Entity
public class SmallObject {
@PrimaryKey (autoGenerate = true)
private int id;
private String smallValue;
}
They are more complicated than this, so I can't use @TypeConverters as Room suggests:
error: Cannot figure out how to save this field into database. You can consider adding a type converter for it.
How do I store this data structure in Room?
I think the best way to answer this is a breif overview in storing structures...
Lists
Room does not support storing lists that are nested inside of a POJO. The recommended way to store lists is to use the foreign key approach. Store the List of objects in a seperate table (in this case a smallObjects table) with a foreign key to their related parent object (in this case "big_object_id"). It should look something like this...
@Entity
public class BigObject {
@PrimaryKey
private int id;
private User user;
@Ignore
private List<SmallObject> smallObjects;
}
@Entity(foreignKeys = {
@ForeignKey(
entity = BigObject.class,
parentColumns = "id",
childColumns = "big_object_fk"
)})
public class SmallObject {
@PrimaryKey (autoGenerate = true)
private int id;
private String smallValue;
@ColumnInfo(name = "big_object_fk")
private int bigObjectIdFk
}
Note that we have added the @Ignore
annotaiton to List<SmallObject>
as we want to ignore the field during Room persistance (as lists are not supported). It now exists so that when we request our list of related small objects from the DB we can still store them in the POJO.
To my knowledge this will mean you are making two queries.
BigObject b = db.BigObjectDao.findById(bOId);
List<SmallObject> s = db.smallObjectDao.findAllSOforBO(bOId);
b.setsmallObjects(s);
It appears that there is a short hand for this in the form of @Relation
Type Converters
These are for cases where you have a complex data structure that can be flattend without losing information, and stored in a single column. A good example of this is the Date object. A Date object is complex and holds a lot of values, so storing it in the database is tricky. We use a type converter to extract the milli representation of a date object and store that. We then convert the millis to a date object on the way out thus keeping our data intact.
Embedded
This is used when you want to take the fields of all nested POJOs in your parent POJO and flatten them out to store in one table. an example :
- name
- age
- location
- x
- y
- DOB
..when embedded this structure would be stored in the database as :
- name
- age
- location_x
- location_y
- DOB
In a sense Embedded exists to save you time creating type converters for every nested object that contains primary type fields like String, int, float, etc...