I'm trying to make an app with Room database. I have one table Bird and one table Family. (One-to-many relationship).
@Entity(tableName ="bird",
foreignKeys =
@ForeignKey(entity = Family.class,
parentColumns = "id",
childColumns = "familyId",
onDelete = CASCADE),
indices = {@Index("familyId")})
public class Bird {
@PrimaryKey(autoGenerate = true)
private int id;
private int familyId;
private String name;
private String family;
private String description;
private String biology;
public Bird(@NonNull String name, @NonNull String family, String description, String biology){
this.name = name;
this.family = family;
this.description= description;
this.biology = biology;
this.familyId = familyId;
}
@Entity(tableName = "family")
public class Family {
@PrimaryKey(autoGenerate = true)
private int id;
private String family;
public Family(@NonNull String family)
{
this.family = family;
}
Everytime I try to run my list of bird (which worked fine before implementing the family entity), nothing shows up and when I try to add a new bird with an @Insert query, I get hit by this :
Caused by: android.database.sqlite.SQLiteConstraintException: FOREIGN KEY constraint failed (code 787 SQLITE_CONSTRAINT_FOREIGNKEY)
at android.database.sqlite.SQLiteConnection.nativeExecuteForLastInsertedRowId(Native Method)
at android.database.sqlite.SQLiteConnection.executeForLastInsertedRowId(SQLiteConnection.java:879)
at android.database.sqlite.SQLiteSession.executeForLastInsertedRowId(SQLiteSession.java:790)
at android.database.sqlite.SQLiteStatement.executeInsert(SQLiteStatement.java:88)
at androidx.sqlite.db.framework.FrameworkSQLiteStatement.executeInsert(FrameworkSQLiteStatement.java:51)
at androidx.room.EntityInsertionAdapter.insert(EntityInsertionAdapter.java:64)
at com.example.room.Dao_Impl.insertBird(Dao_Impl.java:115)
at com.example.room.BirdRepository$InsertBirdAsyncTask.doInBackground(BirdRepository.java:56)
at com.example.room.BirdRepository$InsertBirdAsyncTask.doInBackground(BirdRepository.java:45)
at android.os.AsyncTask$3.call(AsyncTask.java:378)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:289)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:919)
Do you guys have any idea from where that could come from ?
Also am I filling the database right that way ?
private static void fillWithSartingData(Context context){
Dao dao = getInstance(context).dao();
FamilyDao familyDao = getInstance(context).familyDao();
JSONArray birds = loadJSONArray(context);
JSONArray families = loadJSONArray(context);
try{
for(int i = 0; i< families.length(); i++){
JSONObject familyObj = families.getJSONObject(i);
String family = familyObj.getString("FamilieF");
familyDao.insertFamily(new Family(family));
}
for(int i = 0; i< birds.length(); i++){
JSONObject bird = birds.getJSONObject(i);
String engName = bird.getString("NameEng");
String family = bird.getString("FamilieF");
String description = bird.getString("Description");
String biology = bird.getString("Biologie");
dao.insertBird(new Bird(engName, family, description, biology));
}
} catch (JSONException e){
}
}
Thank you! Alex
You have violated foreign key constraint "FOREIGN KEY constraint failed (code 787 SQLITE_CONSTRAINT_FOREIGNKEY)" because you did not set
familyId
in Bird classyou have to set the
familyId
inBird
class before inserting birdto do that add a
familyId
argument to bird constructor like this:insertFamily
infamilyDao
should return Long (if it has one Family argument) or Long Array (if it has vararg Family argument) then you get id of inserted family frominsertFamily
and use it asfamilyId
like this: