房间数据库,用列表构造和查询实体

时间:2018-03-04 03:55:49

标签: android sqlite android-room

这是我的设置。我有一个WorkoutPlan对象,可以包含其中的Workout对象列表。我目前正在建模的方式是通过第三个表来处理两者的映射。 WorkoutPlan可以包含许多锻炼,许多WorkoutPlans可以使用锻炼。

@Entity(tableName = "workoutPlans")
data class DbWorkoutPlan(@ColumnInfo(name = "name")
                         val name: String,
                         @ColumnInfo(name = "date")
                         val date: Date) {

    @PrimaryKey(autoGenerate = true)
    @ColumnInfo(name = "id")
    var id: Int = 0
}

@Entity(tableName = "workouts")
data class DbWorkout(@ColumnInfo(name = "name")
                     val name: String,
                     @ColumnInfo(name = "date")
                     val data: Date) {

    @PrimaryKey(autoGenerate = true)
    @ColumnInfo(name = "id")
    var id: Int = 0
}

@Entity(tableName = "DbWorkoutPlanWorkoutJoin",
    primaryKeys = arrayOf("workoutPlanId", "workoutId"),
    foreignKeys = arrayOf(ForeignKey(entity = DbWorkoutPlan::class,
                                     parentColumns = arrayOf("id"),
                                     childColumns = arrayOf("workoutPlanId")),
                          ForeignKey(entity = DbWorkout::class,
                                     parentColumns = arrayOf("id"),
                                     childColumns = arrayOf("workoutId"))))
data class DbWorkoutPlanWorkoutJoin(@ColumnInfo(name = "workoutPlanId")
                                    val workoutPlanId: Int,
                                    @ColumnInfo(name = "workoutId")
                                    val workoutId: Int)

这就是我对表的数据设置。我不确定它是否正确。在返回的数据方面,我有这个。

data class DbWorkoutPlanResult(@Embedded
                               val workoutPlan: WorkoutPlan,
                               @Relation(parentColumn = "id", entityColumn = "workoutId")
                               val workoutIds: List<DbWorkout>)

所以我想找回一个包含一个WorkoutPlan的DbWorkoutPlanResult和一个包含它的所有锻炼的列表。

我知道我做得不对,而且复杂性正在迅速增加。有谁知道我在设置中做错了什么?我对查询有什么用处?我最好的尝试就是这个

@Query("SELECT * " +
               "FROM DbWorkoutPlanWorkoutJoin " +
               "INNER JOIN workoutPlans " +
               "ON DbWorkoutPlanWorkoutJoin.workoutPlanId = workoutPlans.id " +
               "INNER JOIN workouts " +
               "ON DbWorkoutPlanWorkoutJoin.workoutId = workouts.id ")
fun getWorkoutPlans(): Flowable<List<DbWorkoutPlanResult>>

提前致谢。

1 个答案:

答案 0 :(得分:3)

使用@Relation注释,您可以创建 1:N (一对多)关系。例如,在您的情况下,单个计划可以有多个锻炼,但每个锻炼只能属于一个计划。这显然不是你想要的!

根据您的需求,我假设如下:获取包含POJOs的{​​{1}}列表和关联的plan列表,您需要使用单独的 JOIN表(我猜你已经是)。

获得结果的一种简单方法是将操作划分为两个查询:

  1. 获取所有计划的workouts
  2. 查询加入表,并为每个 List<DbWorkoutPlan>
  3. 获取所有List<DbWorkout>

    示例代码

    首先定义模型

    DbWorkoutPlan

    现在在@Entity(tableName="plans") class DbWorkoutPlan { @PrimaryKey private long id; // ... @Ignore private List<DbWorkout>; // do not persist this, also create getter/setter for this field } @Entity(tableName="workouts") class DbWorkout { @PrimaryKey private long id; // ... } @Entity( tableName="plan_workout_join" primaryKeys = {"workoutPlanId", "workoutId"}, foreignKeys = { @ForeignKey(entity = DbWorkoutPlan.class, parentColumns = "id", childColumns = "plan"), @ForeignKey(entity = DbWorkout.class, parentColumns = "id", childColumns = "workout") } ) class PlanWorkoutJoin { private long plan; private long workout; }

    DAO

    现在您可以查询,

    @Query("SELECT * FROM plans")
    List<DbWorkoutPlan> getAllPlans();
    
    @Query("SELECT * FROM workouts WHERE workouts.id IN (SELECT workout FROM plan_workout_join WHERE plan_workout_join.plan=:plan)")
    List<DbWorkout> getWorkoutsForPlan(long plan);
    

    P.S。如果您使用RxJava,显然需要稍微修改一下,但核心思想保持不变