Android会议室:如何建立关系模型?

时间:2017-05-19 12:16:18

标签: 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 +实体)?

2 个答案:

答案 0 :(得分:22)

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

  

便捷注释,可以在Pojo中自动使用   获取关系实体。当从查询中返回Pojo时,全部   它的关系也是由Room提供的。

See document.

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

答案 1 :(得分:-5)

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