I have two entities; municipality
and city
. Municipalities are assumed to have unique names whereas cities are assumed to be unique within their municipality.
Is there a way to set up a constraint for cities so that the combination of its name and its municipality's name must be unique?
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 testAddSameCityName() {
Database.store.transactional {
val municipality = XdMunicipality.new("Mun 1")
val city = XdCity.new("City")
city.municipality = municipality
}
// Allow insertion of same city name in other municipality
Database.store.transactional {
val municipality = XdMunicipality.new("Mun 2")
val city = XdCity.new("City")
city.municipality = municipality
}
// Do not allow insertion of existing city name in municipality
assertFailsWith<ConstraintsValidationException> {
Database.store.transactional {
val municipality = XdMunicipality.find("Mun 1")
val city = XdCity.new("City")
city.municipality = municipality
}
}
}
The advised approach is to use xdParent
and xdChildren
relations between XdCity and XdMunicipality.
It may be not so easy to change relation when a database has history. To solve the problem with unique names in scope of municipality you can use composite indexes for entity types like here:
companion object : XdNaturalEntityType<XdCity>() {
override val compositeIndices = listOf(
listOf(XdCity:: municipality, ...may goes anything like XdCity::name)
)
}