Search code examples
kotlin-exposed

How to set cascade type in a One-To-Many relationship in Kotlin Exposed?


I have two entities in a One-To-Many relationship. The "One" entity owns the "Many"'s lifecycle. If the "One" entity is deleted, I want all "Many" entities who belong to the "One" to be deleted automatically.

I assume there is a way to set the reference as "CascadeType.DELETE" like in Hibernate, so I don't have to delete all the "Many"s before deleting the "One".

object Apis : IntIdTable() {
    val name = varchar("name", 20)
    val url = varchar("url", 255)
    val method = enumerationByName("method", 20, HttpMethod::class)
    val requestBody = varchar("request_body", 65535)
    val responseDsl = varchar("response_dsl", 65535)
    val responseType = enumerationByName("response_type", 20, ResponseType::class)
    val enabled = bool("enabled")
}

class Api(id: EntityID<Int>) : IntEntity(id){
    companion object : IntEntityClass<Api>(Apis)

    var name by Apis.name
    var url by Apis.url
    var method by Apis.method
    var requestBody by Apis.requestBody
    var responseDsl by Apis.responseDsl
    var responseType by Apis.responseType
    var enabled by Apis.enabled
    val headers by ApiHeader referrersOn ApiHeaders.id
}

object ApiHeaders : IdTable<Int>() {
    override val id = reference("api_id", Apis).primaryKey()
    val key = varchar("key", 255)
    val value = varchar("value", 255)
}

class ApiHeader(id: EntityID<Int>) : Entity<Int>(id) {
    companion object : EntityClass<Int, ApiHeader>(ApiHeaders)

    var api by Api referencedOn ApiHeaders.id
    var key by ApiHeaders.key
    var value by ApiHeaders.value
}

fun main() {
    transaction {
        addLogger(StdOutSqlLogger)
        val api = Api.findById(1)
        // if headers are not deleted, api can't be deleted directly
        api?.headers?.forEach { it.delete() }
        api?.delete()
        commit()
    }
}

I need a way to easily set the desired cascade type of relationship.


Solution

  • reference() and optReference() functions have optional parameters: onUpdate and onDelete.

    In your case you have to write:

    object ApiHeaders : IdTable<Int>() {
        override val id = reference("api_id", Apis, onDelete = ReferenceOption.CASCADE).primaryKey()
        val key = varchar("key", 255)
        val value = varchar("value", 255)
    }