Home > Blockchain >  Parcelable error occurred while using the Room
Parcelable error occurred while using the Room

Time:08-11

Parcelable error occurred while using the Room.

I'm studying Room, but I don't have much common sense yet. So I don't know why I use Parcelable.

I think there was an error when changing the format of Room to one to many.

error mesage :

error: (goalId) does not exist in com.example.goalapp.db.entity.Goal. Available columns are id,goalName

public final class TodayGoal implements android.os.Parcelable {
                                                              ^

Entity related code :

//Goal table
@Parcelize
@Entity(tableName = "goal_table")
data class Goal(
    @PrimaryKey(autoGenerate = true)
    val id: Int,
    val goalName: String,
): Parcelable


//todayGoal table
@Parcelize
@Entity(
    tableName = "today_goal_table",
    foreignKeys = [
        ForeignKey(
            entity = Goal::class,
            parentColumns = ["goalId"],
            childColumns = ["id"],
            onDelete = ForeignKey.CASCADE
        )
    ]
)
data class TodayGoal(
    val id: Int,
    @PrimaryKey(autoGenerate = true)
    val todayGoalId: Int,
    val TodayGoalName: String,
): Parcelable


//GoalAndTodayGoal
@Parcelize
data class GoalAndTodayGoals(
    @Embedded val goal: Goal,
    @Relation(
        parentColumn = "goalId",
        entityColumn = "id"
    )
    val todayGoals: List<TodayGoal>
): Parcelable

CodePudding user response:

As the error say, goalId does not exist in Goal class. Try to change the id attribute of Goal to goalId.

@Parcelize
@Entity(tableName = "goal_table")
data class Goal(
    @PrimaryKey(autoGenerate = true)
    val goalId: Int,
    val goalName: String,
): Parcelable

CodePudding user response:

The Issue

Your issue is that the reference, in the ForeignKey definition as per parentColumns = ["goalId"],, is not pointing to a column that exists in the parent (Goal) table.

The respective (suitable) column is named id as per @PrimaryKey(autoGenerate = true) val id: Int,

  • if you used the goalName column that Room tells you is an available column then you would get a subsequent error as the goalName column is not UNIQUE.

    • a ForeignKey must reference a parent column (or combination of columns) that is/are UNIQUE, as SQLite must be able to ascertain the exact parent not one of more than one parent.

Potential Fixes

1. change the id column name to be goalId so either:-

val goalId: Int,

or if you want the field/member name to remain as id then :-

@ColumnInfo(name = "goalId")
val id: Int
  • Note one of these 2 solutions would be suggested as the better solutions.

2. Change, to use parentColumns = ["id"],.

  • However, using id as column, if not the only column named id, in related tables, can lead to ambiguities (what id column).

    • this issue would not be encountered if not using JOIN in a SELECT statement.
    • The ambiguity and can be circumvented, by using JOIN along with using exact column names, of the ambiguous columns prefixed by the table name and separated from the column name by a ., but that can lead to rather lengthy SQL.

3. Another option would be to do away with the ForeignKey definition altogether BUT even though it isn't needed

  • ForeignKey does not define a relationship, but instead creates a rule (a constraint in SQLite terminology) that enforces referential integrity

  • However, you then lose the built-in assurance of referential integrity and the automatic maintenance of the referential integrity (deletion of a parent being CASCADEed (i.e. the children being deleted if the parent is deleted)).

  • Related