27

我刚刚开始使用 Room,虽然一切似乎都非常直观,但我目前并不真正了解我该如何处理人际关系。

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

  1. 您应该如何建模多对多一对多关系?
  2. 这在实践中会是什么样子(例如 DAO + 实体)?
4

2 回答 2

28

您可以使用@Relation注释来处理 Room 中的关系。

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

见文件。

(谷歌的文档有令人困惑的例子。我已经在另一个答案中写了步骤和一些基本解释。你可以查看一下

于 2017-06-07T23:19:35.547 回答
-6

我创建了一个简单的便捷方法,可以手动填充一对多关系。因此,例如,如果 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;
    });
于 2017-09-10T07:22:19.793 回答