Как каскадно удалить последний связанный элемент с Xodus DNQ - PullRequest
0 голосов
/ 06 марта 2020

У меня есть две сущности; 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 }
    }
}

1 Ответ

1 голос
/ 06 марта 2020

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()
            }
        }
    }

Оба эти механизма вызваны только для транзакции flu sh. Поэтому тест должен быть изменен так:

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