[英]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.