使用Room插入关系实体

使用Room插入关系实体

本文介绍了Android Room:使用Room插入关系实体的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经使用关系在Room中添加了一对多关系.我提到了,用于在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.

该帖子介绍了如何从数据库中读取值,但是将实体存储到数据库中导致userId为空,这意味着两个表之间没有关系.

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.

我不确定在具有userId值的情况下将insert a UserList of Pet插入数据库的理想方法是什么.

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)用户实体:

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

2)宠物实体:

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

3)UserWithPets POJO:

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;
}

现在要从数据库中获取记录,我们使用以下DAO:

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();
}


编辑

我已创建此问题 https://issuetracker.google.com/issues/62848977 在问题跟踪器上.希望他们会为此做些事情.

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

推荐答案

您可以通过将Dao从接口更改为抽象类来实现此目的.

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();
}

您还可以通过使User对象具有@Ignored List<Pet> pets

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
}

,然后Dao可以将UserWithPets映射到用户:

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();
}

您可能想在PetDAO中使用insertAll(List<Pet>)insertPetsForUser(User, List<Pet>)方法...如何划分DAO取决于您! :)

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! :)

无论如何,这只是另一种选择.将您的DAO包装在DataSource对象中也可以.

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

这篇关于Android Room:使用Room插入关系实体的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-23 09:38