📜 ⬆️ ⬇️

Room: One to many

Hello. In the courtyard of 2018 and for almost a year now Google has been actively working on Architecture Components . Good documentation and examples allow you to start using new components without any problems and difficulties. But there is always a fly in the ointment of the code honey . The notes below do not claim to be true, but they may save two to three hours of googling and viewing the code of libraries.

One to many


Everything is simple: the documentation tells you how to organize classes in order to get a one-to-many connection of entities. Take 2 entities:

@Entity public class DialogPojo { @NonNull @PrimaryKey String id; //other fields } @Entity( foreignKeys = @ForeignKey(entity = DialogPojo.class, parentColumns = "id", childColumns = "dialogId", onDelete = ForeignKey.CASCADE), primaryKeys = {"dialogId", "tag"}) public class TagPojo { @NonNull String dialogId; @NonNull String tag; //other fields } 

and link them into a single entity:

 public class DialogWithTags { @Embedded public DialogPojo dialog; @Relation(parentColumn = "id", entity = TagPojo.class, entityColumn = "dialogId") public List<TagPojo> tags; //other fields } 

To get a new DialogWithTags entity, you need to use Dao, which will load data from the DialogPojo table, and tags from the associated table (entity = TagPojo.class) will be automatically loaded:
')
 @Dao public interface DialogDao { @Query("SELECT * FROM DialogPojo WHERE id = :dialogId") LiveData<DialogWithTags> loadDialogBy(String dialogId); @Query("SELECT * FROM DialogPojo WHERE id = :dialogId") DialogWithTags getDialogBy(String dialogId); } 

Using this knowledge you can already collect the death star app. However, in the course of work there may be questions, the answers to which are better known at the preparatory stages.

Integrity


Strange as it may seem, a request to receive DialogWithTags does not guarantee data integrity. That is, it is possible that DialogPojo is already loaded, but the TagPojo list is not. A warning about possible problems appears at the compilation of the program. And who reads these warnings? To ensure data integrity, you must add the Transaction annotation to the request.

 @Dao public interface DialogDao { @Transaction @Query("SELECT * FROM DialogPojo WHERE id = :dialogId") LiveData<DialogWithTags> loadDialogBy(String dialogId); @Transaction @Query("SELECT * FROM DialogPojo WHERE id = :dialogId") DialogWithTags getDialogBy(String dialogId); } 

Preservation


Unfortunately, to save the model DialogWithTags just will not work. You need to save the data separately and, preferably, in a single transaction, for example:

 @Dao public abstract class DialogDao { @Transaction public void insert(DialogWithTags dialogWithTags) { insert(dialogWithTags.dialog); for(TagPojo tag: dialogWithTags.tags) { insert(tag); } } @Insert(onConflict = OnConflictStrategy.IGNORE) public abstract long insert(DialogPojo dialog); @Insert(onConflict = OnConflictStrategy.IGNORE) public abstract long insert(TagPojo tag); .... } 

Live data


The biggest disappointment awaits when using LiveData. Data will only be live for the embedded dialog fields. Changes to tags will not be tracked. Of course, you can declare the tags field as LiveData, but do not forget that LiveData will only return data if at least one observer is registered.

Conclusion


Like any framework, Architecture Components solves a number of tasks, relieves developers of boilerplate code and makes life more beautiful , but also adds its own problems. In my case, the framework has successfully penetrated the project and feels great there.

Source: https://habr.com/ru/post/349280/


All Articles