Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android Room: Insert relation entities using Room

I've added one to many relationship in Room using Relation. I referred to this post to write the following code for relation in Room.

The post tells how to read the values from the database but storing the entities into the database resulted in userId to be empty which means there is no relation between the 2 tables.

I'm not sure what is the ideal way to insert a User and List of Pet into the database while having userId value.

1) User Entity:

@Entity public class User {     @PrimaryKey     public int id; // User id } 

2) Pet Entity:

@Entity public class Pet {     @PrimaryKey     public int id;     // Pet id     public int userId; // User id     public String name; } 

3) UserWithPets POJO:

// Note: No annotation required at this class definition. public class UserWithPets {    @Embedded    public User user;     @Relation(parentColumn = "id", entityColumn = "userId", entity = Pet.class)    public List<Pet> pets; } 

Now to fetch the records from DB we use the following DAO:

@Dao public interface UserDao {     @Insert     fun insertUser(user: User)      @Query("SELECT * FROM User")     public List<UserWithPets> loadUsersWithPets(); } 

EDIT

I have created this issue https://issuetracker.google.com/issues/62848977 on the issue tracker. Hopefully they will do something regarding it.

like image 304
Akshay Chordiya Avatar asked Jun 21 '17 04:06

Akshay Chordiya


People also ask

How would you insert entities with a one to many relationship in a room?

Android one to many in room explanation: Add the @Relation annotation to the instance of the child entity, with parentColumn set to the name of the primary key column of the parent entity and entityColumn set to the name of the column of the child entity that references the parent entity's primary key.

How do I add a room dependency?

Declaring dependencies To add a dependency on Room, you must add the Google Maven repository to your project. Read Google's Maven repository for more information. For information on using Kotlin extensions, see the ktx documentation. For more information about dependencies, see Add Build Dependencies.

Is Room A ORM?

Room is an ORM, Object Relational Mapping library.


1 Answers

You can do this by changing your Dao from an interface to an abstract class.

@Dao public abstract class UserDao {      public void insertPetsForUser(User user, List<Pet> pets){          for(Pet pet : pets){             pet.setUserId(user.getId());         }          _insertAll(pets);     }      @Insert     abstract void _insertAll(List<Pet> pets);  //this could go in a PetDao instead...      @Insert     public abstract void insertUser(User user);      @Query("SELECT * FROM User")     abstract List<UserWithPets> loadUsersWithPets(); } 

You can also go further by having a User object have an @Ignored List<Pet> pets

@Entity public class User {     @PrimaryKey     public int id; // User id      @Ignored     public List<Pet> pets } 

and then the Dao can map UserWithPets to User:

public List<User> getUsers() {     List<UserWithPets> usersWithPets = loadUserWithPets();     List<User> users = new ArrayList<User>(usersWithPets.size())     for(UserWithPets userWithPets: usersWithPets) {         userWithPets.user.pets = userWithPets.pets;         users.add(userWithPets.user);     }     return users; } 

This leaves you with the full Dao:

@Dao public abstract class UserDao {      public void insertAll(List<User> users) {         for(User user:users) {            if(user.pets != null) {                insertPetsForUser(user, user.pets);            }         }         _insertAll(users);     }      private void insertPetsForUser(User user, List<Pet> pets){          for(Pet pet : pets){             pet.setUserId(user.getId());         }          _insertAll(pets);     }      public List<User> getUsersWithPetsEagerlyLoaded() {         List<UserWithPets> usersWithPets = _loadUsersWithPets();         List<User> users = new ArrayList<User>(usersWithPets.size())         for(UserWithPets userWithPets: usersWithPets) {             userWithPets.user.pets = userWithPets.pets;             users.add(userWithPets.user);         }         return users;     }       //package private methods so that wrapper methods are used, Room allows for this, but not private methods, hence the underscores to put people off using them :)     @Insert     abstract void _insertAll(List<Pet> pets);      @Insert     abstract void _insertAll(List<User> users);      @Query("SELECT * FROM User")     abstract List<UserWithPets> _loadUsersWithPets(); } 

You may want to have the insertAll(List<Pet>) and insertPetsForUser(User, List<Pet>) methods in a PetDAO instead... how you partition your DAOs is up to you! :)

Anyway, it's just another option. Wrapping your DAOs in DataSource objects also works.

like image 124
Kieran Macdonald-Hall Avatar answered Sep 26 '22 00:09

Kieran Macdonald-Hall