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/areUNIQUE
, as SQLite must be able to ascertain the exact parent not one of more than one parent.
- a
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 aSELECT
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.
- this issue would not be encountered if not using
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)).