如何使用 Xodus DNQ 级联删除最后一个链接的项目
How to cascade deletion of last linked item with Xodus DNQ
我有两个实体; municipality
和 city
(实际上更多,但在这里简化)。 municipality
必须始终包含至少一个城市。
有没有办法设置一个约束条件,使最终 city
级联的删除也删除其父级 municipality
?
实体
class XdCity(entity: Entity) : XdEntity(entity) {
companion object : XdNaturalEntityType<XdCity>()
var name by xdRequiredStringProp()
var municipality: XdMunicipality by xdLink1(
XdMunicipality::cities,
onDelete = OnDeletePolicy.CLEAR,
onTargetDelete = OnDeletePolicy.CASCADE
)
}
class XdMunicipality(entity: Entity) : XdEntity(entity) {
companion object : XdNaturalEntityType<XdMunicipality>()
var name by xdRequiredStringProp(unique = true)
val cities by xdLink1_N(
XdCity::municipality,
onDelete = OnDeletePolicy.CASCADE,
onTargetDelete = OnDeletePolicy.CLEAR
)
}
测试用例
@Test
fun testCityDeletionCascade() {
Database.store.transactional {
val municipality = XdMunicipality.findOrNew("Mun 1")
XdCity.findOrNew("City A").apply {
this.municipality = municipality
}
XdCity.findOrNew("City B").apply {
this.municipality = municipality
}
}
Database.store.transactional {
XdCity.all().first().delete()
assertTrue { XdMunicipality.all().isNotEmpty }
XdCity.all().first().delete()
assertTrue { XdMunicipality.all().isEmpty }
}
}
Xodus-dnq 有两种机制:XdEntityListener
或 XdEntity#beforeFlush
。两者都可以在这里应用。对于 beforeFlush
:
class XdMunicipality(entity: Entity) : XdEntity(entity) {
companion object : XdNaturalEntityType<XdMunicipality>()
var name by xdRequiredStringProp(unique = true)
val cities by xdLink1_N(
XdCity::municipality,
onDelete = OnDeletePolicy.CASCADE,
onTargetDelete = OnDeletePolicy.CLEAR
)
override fun beforeFlush() {
if (cities.isEmpty) {
delete()
}
}
}
这两种机制仅在事务刷新时调用。所以测试应该这样修改:
@Test
fun testCityDeletionCascade() {
store.transactional {
val municipality = XdMunicipality.findOrNew { name = "Mun 1" }
XdCity.findOrNew { name = "City A" }.apply {
this.municipality = municipality
}
XdCity.findOrNew { name = "City B" }.apply {
this.municipality = municipality
}
}
store.transactional {
XdCity.all().first().delete()
assertTrue { XdMunicipality.all().isNotEmpty }
}
store.transactional {
XdCity.all().first().delete()
}
store.transactional {
assertTrue { XdMunicipality.all().isEmpty }
}
}
我有两个实体; municipality
和 city
(实际上更多,但在这里简化)。 municipality
必须始终包含至少一个城市。
有没有办法设置一个约束条件,使最终 city
级联的删除也删除其父级 municipality
?
实体
class XdCity(entity: Entity) : XdEntity(entity) {
companion object : XdNaturalEntityType<XdCity>()
var name by xdRequiredStringProp()
var municipality: XdMunicipality by xdLink1(
XdMunicipality::cities,
onDelete = OnDeletePolicy.CLEAR,
onTargetDelete = OnDeletePolicy.CASCADE
)
}
class XdMunicipality(entity: Entity) : XdEntity(entity) {
companion object : XdNaturalEntityType<XdMunicipality>()
var name by xdRequiredStringProp(unique = true)
val cities by xdLink1_N(
XdCity::municipality,
onDelete = OnDeletePolicy.CASCADE,
onTargetDelete = OnDeletePolicy.CLEAR
)
}
测试用例
@Test
fun testCityDeletionCascade() {
Database.store.transactional {
val municipality = XdMunicipality.findOrNew("Mun 1")
XdCity.findOrNew("City A").apply {
this.municipality = municipality
}
XdCity.findOrNew("City B").apply {
this.municipality = municipality
}
}
Database.store.transactional {
XdCity.all().first().delete()
assertTrue { XdMunicipality.all().isNotEmpty }
XdCity.all().first().delete()
assertTrue { XdMunicipality.all().isEmpty }
}
}
Xodus-dnq 有两种机制:XdEntityListener
或 XdEntity#beforeFlush
。两者都可以在这里应用。对于 beforeFlush
:
class XdMunicipality(entity: Entity) : XdEntity(entity) {
companion object : XdNaturalEntityType<XdMunicipality>()
var name by xdRequiredStringProp(unique = true)
val cities by xdLink1_N(
XdCity::municipality,
onDelete = OnDeletePolicy.CASCADE,
onTargetDelete = OnDeletePolicy.CLEAR
)
override fun beforeFlush() {
if (cities.isEmpty) {
delete()
}
}
}
这两种机制仅在事务刷新时调用。所以测试应该这样修改:
@Test
fun testCityDeletionCascade() {
store.transactional {
val municipality = XdMunicipality.findOrNew { name = "Mun 1" }
XdCity.findOrNew { name = "City A" }.apply {
this.municipality = municipality
}
XdCity.findOrNew { name = "City B" }.apply {
this.municipality = municipality
}
}
store.transactional {
XdCity.all().first().delete()
assertTrue { XdMunicipality.all().isNotEmpty }
}
store.transactional {
XdCity.all().first().delete()
}
store.transactional {
assertTrue { XdMunicipality.all().isEmpty }
}
}