Search code examples
kotlinkotlin-exposed

Avoid code duplication in insert and update statements using JetBrains Exposed


I'm using Exposed in a new project and I'm noticing that for insert and update statements I have to duplicate all the assignments for record values.

An example:

val orderId = Orders.insert {
    it[orderType] = orderDTO.orderType
    it[deliveryDateTime] = LocalDateTime.of(
        LocalDate.parse(orderDTO.deliveryDate),
        LocalTime.parse(orderDTO.deliveryTime)
    )
    it[customerName] = orderDTO.customerName
    it[customerPhone] = orderDTO.customerPhone
    it[customerAddress] = orderDTO.customerAddress
    
    // ... other fields
} get Orders.id


Orders.update({ Orders.id eq orderId }) { 
    it[orderType] = orderDTO.orderType
    it[deliveryDateTime] = LocalDateTime.of(
        LocalDate.parse(orderDTO.deliveryDate),
        LocalTime.parse(orderDTO.deliveryTime)
    )
    it[customerName] = orderDTO.customerName
    it[customerPhone] = orderDTO.customerPhone
    it[customerAddress] = orderDTO.customerAddress
    
    // ... other fields
}

I'm trying to extract the common assignments in a lambda or function but in the first case the body is of type T.(InsertStatement<Number>)->Unit, while in the update it is a T.(UpdateStatement)->Unit, so I don't see an easy way to achieve this.

Am I missing something or is this by design?


Solution

  • Maybe you could do something like this: a function that has the common input parameters that you can call from the lambdas:

    fun Orders.insertOrUpdate(it: UpdateBuilder<Number>, orderDTO: OrderDTO) {
        it[orderType] = orderDTO.orderType
        it[deliveryDateTime] = LocalDateTime.of(
            LocalDate.parse(orderDTO.deliveryDate),
            LocalTime.parse(orderDTO.deliveryTime)
        )
        it[customerName] = orderDTO.customerName
        it[customerPhone] = orderDTO.customerPhone
        it[customerAddress] = orderDTO.customerAddress
    }
    
    val orderId = Orders.insert { insertOrUpdate(it, orderDTO) } get Orders.id
    
    Orders.update { insertOrUpdate(it, orderDTO) }