After a few months working with Room in Android we have encountered some problems that have really hindered our development compared to other ORM in the market (such as Hibernate). Some of the problems found are the following:
Room in android issues
- Do not allow manual insertion queries, you can only annotate methods with @Insert and define the replacement strategy in case there are conflicts.
- It does not allow to define Foreign Keys as collections within an entity. For example, if we have a Album entity, we can not define a List <Track> as a Foreign Key within it, but force us to put an albumId field annotated as Foreign Key in the track Track entity. This makes the insertions in the Album table not atomic since you have to insert them in two tables separately (nor does it allow custom insertion queries as seen in the first point).
- It does not allow to define the type of return in the insertions. In other words, if we want to insert in a table which Primary Key is defined as String, the insertion method will always return Long (or List <Long> in case we insert several elements), this Long being the rowId.
- By not allowing lists of Foreign Keys in the entities, for reading we have to create a view (in the form of a data class) where we include the relations of the entity that we want to read, so that we have duplicated the database models by every reading of the same entity that we do, having a Featured entity that has only one ID
@Entity(tableName = FeaturedDb.FEATURED_TABLE_NAME) data class FeaturedEntity( @PrimaryKey @ColumnInfo(name = FeaturedDb.FEATURED_ID_FIELD_NAME) var id: String )
And then we have N entities that refer to this Featured through a Foreign Key (in this case it will be only album):
data class AlbumEntity( @PrimaryKey @ColumnInfo(name = AlbumDb.ALBUM_ID_FIELD_NAME) var id: String, var title: String, @ColumnInfo(name = AlbumDb.FEATURED_ID_KEY_FK) var featuredId: String? = null )
If we want to read an FeaturedEntity by ID in a single query, we will have to have an intermediate model such as:
data class FeaturedDbDto( @Embedded var featuredEntity: FeaturedEntity, @Relation( entity = AlbumEntity::class, parentColumn = "id", entityColumn = "featuredId" ) var albums: List = emptyList() )
These are just some of the difficulties we have encountered, although there are undoubtedly many others, which will make us rethink the use of Room in Android in future projects.
However, not everything is so bad. Room in Android also gives us tools that make our life easier.
Room in Android benefits
- The intensive use of annotations means that we do not have to write any code to interact with the database. This is something that, for example, is missed when working with Realm.
- Room in Android provides integration with LiveData and RxJava out of the box, which makes it much easier to create reactive applications without having to deal with the creation of the Observables, which allows us to observe changes in the database to react immediately.