Room:删除 ForeignKey 或将 ForeignKey 设置为默认值
Room: deleting a ForeignKey or setting the ForeignKey to a default value
我有以下实体:
@Entity(indices = {@Index("address")},
foreignKeys = @ForeignKey(
entity = Address.class,
parentColumns = "address",
childColumns = "address",
onUpdate = CASCADE,
onDelete = SET_DEFAULT))
public class Human {
@PrimaryKey(autoGenerate = true)
public long id;
@NonNull
public String name;
@NonNull
public String address;
}
@Entity
public class Address {
@PrimaryKey
@NonNull
public String address;
public int someInt;
}
我用不同的地址添加 "humans",稍后我尝试使用以下方法删除或编辑:
@Insert(onConflict = REPLACE)
void add(Human human);
我看到的选项和它们的问题:
我有一个地址列表,其中一个是 "default"。当我删除一个地址时,我希望位于被删除地址的"Humans"到"move"到"default"。
我用过:
@Query("delete from Address where address = :address")
void deleteAddress(String address);
所以 onDelete = SET_DEFAULT 似乎并没有像我想象的那样工作,如果我在人类实体中设置默认值地址。
当前失败:NOT NULL 约束失败。
删除的替代方法是编辑地址并将其设置为 "default",从而与现有的 "default" 条目合并。
我试过了:
@Query("update Address SET address = :address WHERE address = :addressToEdit")
void editAddress(String addressToEdit, String newAddress);
这当前失败了:UNIQUE 约束失败。 因为已经有一个同名的地址,显然。
在两个实体中将地址设置为@Nullable。这样,"default"地址为空。这给我的解决方案增加了额外的复杂性(我不喜欢它)而且我似乎无法使用以下代码查询具有空地址的 Humans,因为它没有 return 任何东西。
@Query("select * from Human where address = :address")
LiveData<List<Human>> getHumans(String address);
如何将此设置设为默认的已删除地址(外键)?
我建议修改您的地址实体并将 id 字段添加为自动递增的整数。然后在人类实体中,您可以通过 id 字段引用地址。因此,在删除地址记录之前,您可以使用要删除的默认引用 ID 更新人类记录,例如:1 然后您可以通过其 ID 删除此地址记录。在这里你可以解决地址唯一约束问题。
到目前为止,我最好的解决方案是使用问题中的第三个选项:
@Query("select * from Human where address is NULL")
LiveData<List<Human>> getAllHumansWithNullAddress();
与默认使用 NULL 一样。
Address
保持不变,但人类变为:
@Entity(indices = {@Index("address")},
foreignKeys = @ForeignKey(
entity = Address.class,
parentColumns = "address",
childColumns = "address",
onUpdate = CASCADE,
onDelete = SET_NULL))
public class Human {
@PrimaryKey(autoGenerate = true)
public long id;
@NonNull
public String name;
@Nullable
public String address;
}
当前 room 不支持 onDelete = SET_DEFAULT 操作,room 将其视为与 onDelete = SET_NULL 相同,所以我建议如下:-
@Entity(foreignKeys = @ForeignKey(
entity = Address.class,
parentColumns = "address",
childColumns = "fk_address_id",
onUpdate = CASCADE,
onDelete = SET_DEFAULT))
public class Human {
@PrimaryKey(autoGenerate = true)
public long id;
@NonNull
public String name;
@Nullable
public String getFk_address_id() {
return fk_address_id;
}
public void setFk_address_id(@Nullable String fk_address_id) {
this.fk_address_id = fk_address_id;
}
//default address doesn't work on delete as room doesn't support
// on delete set default and treat it like set null
@Nullable
public String fk_address_id = "default address";
public Human(@NonNull String name, @Nullable String fk_address_id) {
this.name = name;
this.fk_address_id = fk_address_id;
}
}
这里是地址字段唯一的地址实体。
@Entity(indices = {@Index(value = {"address"},
unique = true)})
public class Address {
public void setAddress(@NonNull String address) {
this.address = address;
}
@PrimaryKey(autoGenerate = true)
@NonNull
int id;
public String address = "default address";
public int someInt;
public Address(@NonNull String address, int someInt) {
this.address = address;
this.someInt = someInt;
}
}
并且在 HumanDao 中你可以获得空引用地址并将它们更新为默认地址。
人道:
@Query("SELECT * FROM Human where fk_address_id IS NULL")
Human[] getNullRef();
地址道:
@Update
void updateAddresses(Address... addresses);
异步任务class
protected Void doInBackground(Void... voids) {
AppDatabase db = AppDatabase.getDatabase(getApplicationContext());
Address address = db.addressDao().getAddress("address to delete");
if(address != null) {
db.addressDao().delete(address);
Human [] humans = db.humanDao().getNullRef();
for(int i =0; i < humans.length; i++) humans[i].setFk_address_id(DEFAULT_ADDRESS);
db.humanDao().updateHumans(humans);
}
return null;
}
我有以下实体:
@Entity(indices = {@Index("address")},
foreignKeys = @ForeignKey(
entity = Address.class,
parentColumns = "address",
childColumns = "address",
onUpdate = CASCADE,
onDelete = SET_DEFAULT))
public class Human {
@PrimaryKey(autoGenerate = true)
public long id;
@NonNull
public String name;
@NonNull
public String address;
}
@Entity
public class Address {
@PrimaryKey
@NonNull
public String address;
public int someInt;
}
我用不同的地址添加 "humans",稍后我尝试使用以下方法删除或编辑:
@Insert(onConflict = REPLACE)
void add(Human human);
我看到的选项和它们的问题:
我有一个地址列表,其中一个是 "default"。当我删除一个地址时,我希望位于被删除地址的"Humans"到"move"到"default"。 我用过:
@Query("delete from Address where address = :address") void deleteAddress(String address);
所以 onDelete = SET_DEFAULT 似乎并没有像我想象的那样工作,如果我在人类实体中设置默认值地址。
当前失败:NOT NULL 约束失败。
删除的替代方法是编辑地址并将其设置为 "default",从而与现有的 "default" 条目合并。 我试过了:
@Query("update Address SET address = :address WHERE address = :addressToEdit") void editAddress(String addressToEdit, String newAddress);
这当前失败了:UNIQUE 约束失败。 因为已经有一个同名的地址,显然。
在两个实体中将地址设置为@Nullable。这样,"default"地址为空。这给我的解决方案增加了额外的复杂性(我不喜欢它)而且我似乎无法使用以下代码查询具有空地址的 Humans,因为它没有 return 任何东西。
@Query("select * from Human where address = :address") LiveData<List<Human>> getHumans(String address);
如何将此设置设为默认的已删除地址(外键)?
我建议修改您的地址实体并将 id 字段添加为自动递增的整数。然后在人类实体中,您可以通过 id 字段引用地址。因此,在删除地址记录之前,您可以使用要删除的默认引用 ID 更新人类记录,例如:1 然后您可以通过其 ID 删除此地址记录。在这里你可以解决地址唯一约束问题。
到目前为止,我最好的解决方案是使用问题中的第三个选项:
@Query("select * from Human where address is NULL")
LiveData<List<Human>> getAllHumansWithNullAddress();
与默认使用 NULL 一样。
Address
保持不变,但人类变为:
@Entity(indices = {@Index("address")},
foreignKeys = @ForeignKey(
entity = Address.class,
parentColumns = "address",
childColumns = "address",
onUpdate = CASCADE,
onDelete = SET_NULL))
public class Human {
@PrimaryKey(autoGenerate = true)
public long id;
@NonNull
public String name;
@Nullable
public String address;
}
当前 room 不支持 onDelete = SET_DEFAULT 操作,room 将其视为与 onDelete = SET_NULL 相同,所以我建议如下:-
@Entity(foreignKeys = @ForeignKey(
entity = Address.class,
parentColumns = "address",
childColumns = "fk_address_id",
onUpdate = CASCADE,
onDelete = SET_DEFAULT))
public class Human {
@PrimaryKey(autoGenerate = true)
public long id;
@NonNull
public String name;
@Nullable
public String getFk_address_id() {
return fk_address_id;
}
public void setFk_address_id(@Nullable String fk_address_id) {
this.fk_address_id = fk_address_id;
}
//default address doesn't work on delete as room doesn't support
// on delete set default and treat it like set null
@Nullable
public String fk_address_id = "default address";
public Human(@NonNull String name, @Nullable String fk_address_id) {
this.name = name;
this.fk_address_id = fk_address_id;
}
}
这里是地址字段唯一的地址实体。
@Entity(indices = {@Index(value = {"address"},
unique = true)})
public class Address {
public void setAddress(@NonNull String address) {
this.address = address;
}
@PrimaryKey(autoGenerate = true)
@NonNull
int id;
public String address = "default address";
public int someInt;
public Address(@NonNull String address, int someInt) {
this.address = address;
this.someInt = someInt;
}
}
并且在 HumanDao 中你可以获得空引用地址并将它们更新为默认地址。
人道:
@Query("SELECT * FROM Human where fk_address_id IS NULL")
Human[] getNullRef();
地址道:
@Update
void updateAddresses(Address... addresses);
异步任务class
protected Void doInBackground(Void... voids) {
AppDatabase db = AppDatabase.getDatabase(getApplicationContext());
Address address = db.addressDao().getAddress("address to delete");
if(address != null) {
db.addressDao().delete(address);
Human [] humans = db.humanDao().getNullRef();
for(int i =0; i < humans.length; i++) humans[i].setFk_address_id(DEFAULT_ADDRESS);
db.humanDao().updateHumans(humans);
}
return null;
}