安卓机房 : Insert relation entities using Room

标签 android android-room android-architecture-components

我使用 Relation 在 Room 中添加了一对多关系. 我提到了this post为 Room 中的关系编写以下代码。

这篇文章讲述了如何从数据库中读取值,但将实体存储到数据库中导致 userId 为空,这意味着这两个表之间没有关系。

我不确定在拥有 的同时将 insert UserList of Pet 放入数据库的理想方法是什么userId 值。

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:

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

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

@Dao
public interface UserDao {
    @Insert
    fun insertUser(user: User)

    @Query("SELECT * FROM User")
    public List<UserWithPets> loadUsersWithPets();
}

编辑

我创建了这个问题 https://issuetracker.google.com/issues/62848977在问题跟踪器上。希望他们会为此做点什么。

最佳答案

您可以通过将 Dao 从接口(interface)更改为抽象类来做到这一点。

@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

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

    @Ignored
    public List<Pet> pets
}

然后道可以映射UserWithPets给用户:

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

这给你留下了完整的道:

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

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

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

关于安卓机房 : Insert relation entities using Room,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44667160/

相关文章:

android - 错误 : Entities and Pojos must have a usable public constructor and Cannot find setter for field

java - Android Room一对一实体关系

android - 在顶部添加新项目后,回收器 View 不会滚动到顶部,因为尚未发生对列表适配器的更改

java - Android:防止按钮上的多个 onClick 事件(已禁用)

java - 以编程方式更改模型纹理 libgdx

android - Android Map底部的RecyclerView

android - PagedListAdapter.submitList() 在更新现有项目时表现异常

javascript - 将文件从 android_asset 文件夹复制到 SD 卡

android - 开始时在 Room 中添加数据的最佳方法是什么?

android - Android Paging Libray 架构组件中 PagingDataAdapter 和 PagedListAdapter 的区别