루틴 수정을 구현하면서 DB 내용을 확인해보니 따로 삭제된 목록에 대해서 삭제하는 쿼리를 수행하지 않았는데 삭제가 되는 것을 확인하였다.

dao 구현체에서 따로 삭제를 수행해주는 것인가 싶어 구현체를 확인하니 그러한 작업은 하지 않고 있었고 답은 쿼리에 있었다.

@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insertRoutine(
    routine: Routine,
    days: List<Day>,
    exercises: List<Exercise>,
    sets: List<ExerciseSet>
)
@Override
public String createQuery() {
  return "INSERT OR REPLACE INTO `routine` (`routine_id`,`title`,`author`,`description`,`modified_date`) VALUES (?,?,?,?,?)";
}

@Insert를 추가한 함수에 충돌 전략으로 OnConflictStrategy.REPLACE를 적용한다면 위처럼 dao 구현체에서 쿼리를 INSERT OR REPLACE로 수행하게 된다.

INSERT OR REPLACE와 삭제한 목록이 DB에 반영되는 것이 무슨 상관이 있을까?

SQLite의 문서의 conflict-clause 내용에서 REPLACE가 수행하는 동작을 보고 알 수 있었다.

결국 루틴 데이터를 저장하면서 Primary Key 제약 조건 위반이 발생하였고 기존 루틴을 삭제하게 된다.

@Entity(
    tableName = "day",
    foreignKeys = [
        ForeignKey(
            entity = Routine::class,
            parentColumns = ["routine_id"],
            childColumns = ["routine_id"],
            onDelete = CASCADE
        )
    ]
)
data class Day @JvmOverloads constructor(
    @PrimaryKey
    @ColumnInfo(name = "day_id")
    val dayId: String,
    @ColumnInfo(name = "routine_id")
    val routineId: String,
    @ColumnInfo(name = "order")
    val order: Int,
    @Ignore
    val exercises: List<Exercise> = emptyList()
)