Updated 14 October 2019
In this blog, we will learn about saving complex objects using android room library.
If you have no knowledge about the android room, then you should first read this article:
After reading this article, you get to know how easy now it is to create a table in your android application. It is just like creating a model class ( a Custom object).
This room library has saved us a lot from the boilerplate code that we used to write for creating a table.But when you start using in the real world scenarios, then you see that you have complex models which have one or more list of objects and some child objects. And room only recognizes the primitive datatypes.
Now you have two options :
Before we go further, let’s first understand what this @Embedded annotation is and what it will do?
As per official docs: @Embedded can be used as an annotation on a field of an Entity or Pojo to signal that nested fields (i.e. fields of the annotated field’s class) can be referenced directly in the SQL queries.
What this means is that if you have some child object in your Model( Entity) class, then when creating the table, the number of columns will be automatically increased to fit in your child object as well. The total number of columns now will be ( Number of columns in your model class + number of columns(fields that make up your object) in your child object class).
But this will only help you save the child object and not the list as we have still not used anything that will help the room to identify the list of objects. for this purpose, we will use type converters.
Type Converter specifies additional type converters that Room can use. The TypeConverter is added to the scope of the element so if you put it on a class/interface, all methods/fields in that class will be able to use the converters.
Now enough of theory and explanation, let’s have a look at the coding part.
Model(Object) Class: This class I need to save to my table.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
@Entity(tableName = "my_table") public class MyData { @PrimaryKey(autoGenerate = true) private int id; @ColumnInfo(name = "ListData") @TypeConverters(DataTypeConverter.class) private List<MyListObject> mList = null; @Embedded private User mUser; public MyData() { } public int getId() { return id; } public void setId(int id) { this.id = id; } public List<MyListObject> getList() { return mList; } public void setList(List<MyListObject> list) { this.mList = list; } public User getUser() { return mUser; } public void setUser(User user) { this.mUser = user; } } |
User.class :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
public class User { @ColumnInfo(name = "first_name") private String firstName; @ColumnInfo(name = "last_name") private String lastName; public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } } |
DataTypeConverter.class: This class will help Android room to convert the list into a primitive data type ( String) and save it in the table.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
public class DataTypeConverter { private static Gson gson = new Gson(); @TypeConverter public static List<MyListObject> stringToList(String data) { if (data == null) { return Collections.emptyList(); } Type listType = new TypeToken<List<MyListObject>>() {}.getType(); return gson.fromJson(data, listType); } @TypeConverter public static String ListToString(List<MyListObject> someObjects) { return gson.toJson(someObjects); } } |
Ok, till now we understood the use of type converter, but still wondering what the @Embedded annotation did.
When Room will create your table.(my_table in our case). The table will have 4 columns ( 2 for the object that you are using and 2 for the embedded child object).
That’s it. Hope this helps you understand the room architecture and how you will be able to save the real world objects using room easily.
If you have more details or questions, you can reply to the received confirmation email.
Back to Home
6 comments
Yes, if you define User as an @Entity, then data of users will be saved in a separate table.
But then you might have to use foreign keys for embedding the user refrence in your my_table .
For more details, you can check the official documentation here –> https://developer.android.com/training/data-storage/room
Hope this helps you 🙂
I suppose , ROOM shouldn’t create a column for mUser, bcoz, ROOM is creating columns for mUser’s fields namely first_name and last_name right?
thanks for the correction, I will update this correction in the blog right away.
This totally depends on the structure you want.
If you have some scenario where you need to query the child key as well, then you should definitely use the embedded notations in your model calsses.
But if you just want to save all of the children data in one class then you can have a typeconverter that converts all your child classes to a string and save that in your model class itself.