Android студия и комната - внешние ключи и ограничение не удалось - PullRequest
1 голос
/ 25 марта 2020

Я пытаюсь создать приложение с базой данных Room. У меня есть один стол Bird и один стол Family. (Отношение один ко многим).

@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;
    }

Каждый раз, когда я пытаюсь запустить свой список птиц (который работал до реализации семейного объекта), ничего не появляется, и когда я пытаюсь добавить новая птица с запросом @Insert, меня поразило это:

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)

У вас, ребята, есть идеи, откуда это может появиться?

Также я правильно заполняю базу данных сюда ?

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){

    }
}

Спасибо! Alex

1 Ответ

0 голосов
/ 25 марта 2020

Вы нарушили ограничение внешнего ключа «Сбой ограничения FOREIGN KEY (код 787 SQLITE_CONSTRAINT_FOREIGNKEY)», так как вы не установили familyId в классе Bird

, вам необходимо установить familyId в Bird классе перед вставкой bird

для этого добавьте аргумент familyId в конструктор bird, например:

public Bird(@NonNull String name, @NonNull String family, String description, String biology, long familyId){
        this.name = name;
        this.family = family;
        this.description= description;
        this.biology = biology;
        this.familyId = familyId;
    }

insertFamily в familyDao должен вернуть Long (если у него один аргумент Family ) или Long Array (если он имеет аргумент семейства vararg), тогда вы получаете идентификатор вставленного семейства из insertFamily и используете его как familyId следующим образом:

for(int i = 0; i< families.length(); i++){
       JSONObject familyObj = families.getJSONObject(i);
       String family = familyObj.getString("FamilieF");
       long familyId = familyDao.insertFamily(new Family(family));// get familyId


       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, familyId));// use familyId
        }
...