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.
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.
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.
Room is an ORM, Object Relational Mapping library.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With