【问题标题】:Android Room @Relation many-to-many?Android Room @Relation 多对多?
【发布时间】:2018-07-16 09:15:03
【问题描述】:

我正在开发一个 Android 应用程序,并在 Android 操作系统中使用新的架构组件:LiveData、ViewModel 和 Room。 我对 Room 实现有一个小问题,即创建一个 @Relation,它从 JOIN 查询(​​多对多关系)返回结果。

我的数据库结构如下所示:

@Entity
public class Student{
  @PrimaryKey
  private int id;
  private String name;
  private String email;
} 

@Entity
public class Group{
  @PrimaryKey
  private int id;
  private String name;
}

@Entity(foreignKeys = {
            @ForeignKey(entity = Student.class,
                    parentColumns = "id",
                    childColumns = "student_id"),
            @ForeignKey(entity = Group.class,
                    parentColumns = "id",
                    childColumns = "group_id")
    })
public class StudentGroup{

  private int studentId;
  private int groupId;
}

我如何才能获得仅针对特定学生的所有组,像这样?

public class StudentWithGroups{
  @Relation(parentColumn = "id", entityColumn = "rule_id", entity = 
StudentGroup.class)
  private List<Group> groups;
}

我已经检查过How can I represent a many to many relation with Android Room?Android Persistence room: "Cannot figure out how to read this field from a cursor" 之类的问题

【问题讨论】:

    标签: android many-to-many android-room android-livedata


    【解决方案1】:

    我如何才能获得仅针对特定学生的所有组,诸如此类?

    this sample code,我有:

      @Query("SELECT categories.* FROM categories\n"+
        "INNER JOIN customer_category_join ON categories.id=customer_category_join.categoryId\n"+
        "WHERE customer_category_join.customerId=:customerId")
    List<Category> categoriesForCustomer(String customerId);
    

    将其转换为您的实体会产生如下结果:

      @Query("SELECT Group.* FROM Group\n"+
        "INNER JOIN StudentGroup ON Group.id=StudentGroup.groupId\n"+
        "WHERE StudentGroup.studentId=:studentId")
    List<Group> groupsForStudent(String studentId);
    

    一般来说,使用 Room,计算出忽略 Room 的 SQL,然后在 DAO 中使用该 SQL。

    【讨论】:

    • 是的,我可以使用 Query 来使用某种 JOIN,但我想知道是否有办法将此 Query 的结果放入保留 Relation-s 的类中。我的意思是,想从某个表中获取整个对象及其所有关系数据。例如,如果我有表 Student、Groups 和 StudentGroup,我希望 StudentDao 从 Students 表中返回所有数据以及 Group 对象列表。希望解释清楚:)
    • @MrVasilev:我认为今天的房间不可能。
    • 谢谢。我的研究以同样的答案结束。希望在下一个版本中添加
    • 您是否已经为 Room 创建了功能请求?我认为这将是一个非常好的功能。即使内部实现会在事务中使用两个不同的查询,如果 Room 能够检测到何时可以使用“加入”实体和完整的 M:N,您也可以节省大量代码和时间在@Relation 字段中。类似@Relation([...] joinEntity=StudentGroups.class, joinEntityColumn="studentId")
    • @fast3r:“您是否已经为 Room 创建了功能请求?” -- 不是为了这个,抱歉。
    【解决方案2】:

    通过房间内Junction的介绍,您可以轻松处理多对多关系。

    修改学生表和组表的主键为:

    @Entity
    public class Student{
      @PrimaryKey
      private int sId;
      private String name;
      private String email;
    } 
    
    @Entity
    public class Group{
      @PrimaryKey
      private int gId;
      private String name;
    }
    
    @Entity(foreignKeys = {
            @ForeignKey(entity = Student.class,
                    parentColumns = "sId",
                    childColumns = "studentId"),
            @ForeignKey(entity = Group.class,
                    parentColumns = "gId",
                    childColumns = "groupId")
    })
    public class StudentGroup{
      private int studentId;
      private int groupId;
    }
    

    您可以获取所有特定学生组:

     public class StudentWithGroups{
       @Embedded
       Student student;
       @Relation(
             parentColumn = "sId",
             entity = Group.class,
             entityColumn = "gId",
             associateBy = @Junction(
                     value = StudentGroup.class,
                     parentColumn = "studentId",
                     entityColumn = "groupId)
       )
       List<Group> groups;
     }
    

    现在您可以查询数据库以获取结果:

     @Dao
     public interface StudentDao {
       @Query("SELECT * FROM Student")
       List<StudentWithGroups> getGroupsOfStudent();
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-07-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-10-25
      相关资源
      最近更新 更多