Android Room:如何建立关系模型?

2017-05-19 android database sqlite orm android-room

我刚刚开始与Room一起工作,尽管一切似乎都很直观,但我目前还不太了解如何正确处理人际关系。

因为SQLite是关系数据库,所以您可以指定对象之间的关系。即使大多数ORM库都允许实体对象相互引用,Room明确禁止这样做。即使您不能使用直接关系,Room仍允许您定义实体之间的外键约束。(来源: https : //developer.android.com/topic/libraries/architecture/room.html#no-object-references

  1. 您应该如何为多对多一对多关系建模?
  2. 实际上这是什么样的(示例DAO和实体)?

Answers

您可以使用@Relation注解在Room中处理关系。

方便注释,可在Pojo中使用,以自动 获取关系实体。当查询返回Pojo时,所有 它的关系也由Room获取。

参见文件。

(Google的文档中有一些令人困惑的示例。我在另一个答案中写了步骤和一些基本的解释。您可以查看一下

我创建了一个简单的便捷方法,该方法手动填充一对多关系。 因此,例如,如果在Country和City之间有一对多的关系,则可以使用该方法在Country中手动填充cityList属性。

/**
 * @param tableOne The table that contains the PK. We are not using annotations right now so the pk should be exposed via a getter getId();
 * @param tableTwo The table that contains the FK. We are not using annotations right now so the Fk should be exposed via a getter get{TableOneName}Id(); eg. getCountryId();
 * @param <T1>     Table One Type
 * @param <T2>     Table Two Type
 * @throws NoSuchFieldException
 * @throws IllegalAccessException
 * @throws NoSuchMethodException
 * @throws InvocationTargetException
 */
private static <T1, T2> void oneToMany(List<T1> tableOne, List<T2> tableTwo) throws NoSuchFieldException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {

    String tableOneName = tableOne.get(0).getClass().getSimpleName();
    String tableTwoName = tableTwo.get(0).getClass().getSimpleName();
    for (T1 t1 :
            tableOne) {
        Method method = t1.getClass().getMethod("getId");
        Integer pkId = (Integer) method.invoke(t1);
        List<T2> listForCurrentId = new ArrayList<>();
        for (T2 t2 : tableTwo) {
            Method fkMethod = t2.getClass().getDeclaredMethod("get".concat(tableOneName).concat("Id"));
            Integer fkId = (Integer) fkMethod.invoke(t2);
            if (pkId == fkId) {
                listForCurrentId.add(t2);
            }
        }
        Method tableTwoList = t1.getClass().getMethod("set".concat(tableTwoName).concat("List"), List.class);
        tableTwoList.invoke(t1, listForCurrentId);
    }
}

这就是我的用法。

   SystemDefaults systemDefaults = new SystemDefaults();
    return Single.zip(systemDao.getRoles(), systemDao.getCountries(), systemDao.getCities(), (roles, countries, cities) -> {
        systemDefaults.setRoles(roles);
        *ConvenienceMethods.oneToMany(countries,cities);*
        systemDefaults.setCountries(countries);
        return systemDefaults;
    });

Related