簡體   English   中英

Android 房間外鍵 onDelte = 級聯無效

[英]Android Room Foreign Key onDelte = Cascade has no effect

我有兩個表之間的一對多關系。 父表是“人物”,子表是“寵物”。 一個人可以養很多寵物。 一只寵物只能擁有一個人。

我使用@Relation 在 PersonWithPets.java 中創建兩個表之間的關系。 在 Pets.java 中,我使用帶有 onDelete = CASCADE 的 ForeignKey。 但是如果我刪除了一個 Person,對應的 Pets 會保留在數據庫中,我不知道為什么。 我幾乎似乎 onDelte = CASCADE 沒有效果。 也許我沒有使用正確的 id,但我已經經歷了很多次,似乎無法弄清楚為什么一個人的寵物沒有與該人一起刪除。

當然,我可以使用寵物的 personId 來迭代和刪除所有共享相同 personId 的 Pet,但這似乎違背了@ForeignKey 注釋的目的。

我會錯過什么? 對不起,如果這很明顯。 我是 Android 的新手。

人.java

@Entity(tableName = "person")
public class Person {
    @PrimaryKey(autoGenerate = true)
    private Integer id;

    String name;

    @Ignore
    private List<Pet> pets = null;

    public Person(){
        // empty constructor for serialization
    }

    @Ignore
    public Person(String name, List<Pet> pets) {
        this.name = name;
        this.pets = pets;
    }

    public Person(PersonWithPets personWithPets) {
        this.id = personWithPets.getPerson().getId();
        this.name = personWithPets.getPerson().getName();
        this.pets = this.getPets(personWithPets);
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public Integer getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public void setPet(Pet pet) {
        if (this.pets == null) {
            this.pets = new ArrayList<>();
        }
        this.pets.add(pet);
    }

    public List<Pet> getPets() {
        return this.pets;
    }

    private List<Pet> getPets(PersonWithPets personWithPets) {
        return personWithPets.getPets();
    }

    public void setName(String name) {
        this.name = name;
    }
}

寵物.java

@Entity(tableName = "pet")
public class Pet {
    @PrimaryKey(autoGenerate = true)
    private Integer id;

    String name;

    public Pet() {
    }

    /**
     * @param name
     */
    @Ignore
    public Pet(String name) {
        this.name = name;
    }

    @ForeignKey
            (entity = Person.class,
                    parentColumns = "id",
                    childColumns = "personId",
                    onDelete = CASCADE,
                    onUpdate = CASCADE)
    private Integer personId;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getPersonId() {
        return personId;
    }

    public void setPersonId(Integer personId) {
        this.personId = personId;
    }
}

PersonWithPets.java

public class PersonWithPets {
    @Embedded public Person person;

    @Relation(
            parentColumn = "id",
            entityColumn = "personId",
            entity = Pet.class
    )
    public List<Pet> pets;

    public Person getPerson() {
        return person;
    }

    public List<Pet> getPets() {
        return pets;
    }
}

個人資料庫

public class PersonRepository {
    private static final String TAG = "RecipeRepository";
    private PersonDao personDao;
    private LiveData<List<Person>> people;
    private LiveData<List<PersonWithPets>> peopleWithPets;
    private LiveData<List<Pet>> pets;

    public PersonRepository (Application application) {
        PersonDatabase db = PersonDatabase.getInstance(application);
        personDao = db.personDao();
        people = personDao.getAllPeople();
        peopleWithPets = personDao.getAllPeopleWithPets();
        pets = personDao.getAllPets();
    }

    // Get all people with pets
    public LiveData<List<PersonWithPets>> getAllPeopleWithPets() {
        return peopleWithPets;
    }

    // Delete
    public void delete(Person person) {
        new DeletePersonAsyncTask(personDao).execute(person);
    }

    // Delete All People
    private static class DeleteAllPeopleAsyncTask extends AsyncTask<Void, Void, Void> {
        private PersonDao personDao;
        private DeleteAllPeopleAsyncTask(PersonDao personDao) {
            this.personDao = personDao;
        }
        @Override
        protected Void doInBackground(Void... voids) {
            personDao.deleteAllPeople();
            //personDao.deleteAllPets();
            return null;
        }
    }
 }

數據庫

@Database(entities = {Person.class, Pet.class}, version = 5, exportSchema = false)
public abstract class PersonDatabase extends RoomDatabase {

    private static final String TAG = "PersonDatabase";
    private static PersonDatabase instance;
    public abstract PersonDao personDao();

    public static synchronized PersonDatabase getInstance(Context context) {
        if(instance == null){
            instance = Room.databaseBuilder(context.getApplicationContext(),
                    PersonDatabase.class, "person_database")
                    .fallbackToDestructiveMigration()
                    .addCallback(roomCallback)
                    .build();
        }
        return instance;
    }

    private static RoomDatabase.Callback roomCallback = new RoomDatabase.Callback(){
        @Override
        public void onCreate(@NonNull SupportSQLiteDatabase db) {
            super.onCreate(db);
            new PopulateDbAsyncTask(instance).execute();
        }
    };

    private static class PopulateDbAsyncTask extends AsyncTask<Void, Void, Void> {
        private PersonDao personDao;
        private PopulateDbAsyncTask(PersonDatabase db){
            personDao = db.personDao();
        }
        @Override
        protected Void doInBackground(Void... voids) {
            Person adam = new Person();
            adam.setName("Adam");
            Pet dog = new Pet();
            dog.setName("Dog");
            adam.setPet(dog);
            Long personId = personDao.insertPerson(adam);
            for (Pet pet : adam.getPets()) {
                pet.setPersonId(personId.intValue());
                personDao.insertPet(pet);
            }
            return null;
        }
    }
}

@Dao
public interface PersonDao {
    @Transaction
    @Insert
    Long insertPerson(Person person);

    @Transaction
    @Insert
    void insertPet(Pet pet);

    @Transaction
    @Update
    int updatePerson(Person person);

    @Transaction
    @Delete
    void deletePerson(Person person);

    @Transaction
    @Query("DELETE FROM person")
    void deleteAllPeople();

    @Transaction
    @Query("DELETE FROM pet")
    void deleteAllPets();

    @Transaction
    @Query("SELECT * FROM person")
    LiveData<List<Person>> getAllPeople();

    @Transaction
    @Query("SELECT * FROM person")
    LiveData<List<PersonWithPets>> getAllPeopleWithPets();

    @Transaction
    @Query("SELECT * FROM pet")
    LiveData<List<Pet>> getAllPets();
}

主要活動

viewModel.getAllPeopleWithPets().observe(this, new Observer<List<PersonWithPets>>() {
            @Override
            public void onChanged(@Nullable List<PersonWithPets> peopleWithPets) {
                Log.d(TAG, "onChanged: --------------------------------");
                Log.d(TAG, "onChanged: ALL PEOPLE WITH PETS");
                for (PersonWithPets personWithPets : peopleWithPets) {
                    Log.d(TAG, "onChanged: Name: " + personWithPets.getPerson().getName() + " ID: " + personWithPets.getPerson().getId());
                    Log.d(TAG, "onChanged: Pets: " + + personWithPets.getPets().size());
                    if (personWithPets.getPets().size() > 0) {
                        for (Pet pet : personWithPets.getPets()) {
                            Log.d(TAG, "onChanged: Name: " + pet.getName() + " ID: " + pet.getId() + " PersonID: " + pet.getPersonId());
                        }
                    } else {
                        Log.d(TAG, "onChanged: No pets.");
                    }
                }
                Log.d(TAG, "onChanged: --------------------------------");
                setTitle("People: " + peopleWithPets.size() + " Pets: " + viewModel.getAllPets().getValue().size());
            }
        });

嘗試將 ForeignKey 注釋從字段聲明中刪除到實體的頂部:

@Entity(tableName = "pet", foreignKeys = @ForeignKey
    (entity = Person.class,
            parentColumns = "id",
            childColumns = "personId",
            onDelete = CASCADE,
            onUpdate = CASCADE))
public class Pet {
    @PrimaryKey(autoGenerate = true)
    private Integer id;
.......................

似乎放在字段上方的@ForeignKey 對創建外鍵根本沒有影響。 您可以在自動生成的數據庫 Java class 中看到它,並使用任何 SQLite 瀏覽器檢查表的結構。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM