Search code examples
ktorkotlin-exposed

CRUD with table relationship using KTOR and EXPOSED


I'm having problems with KTOR and EXPOSED for a crud using relationship between tables. I configured my service as follows:

class LegalPersonService {

    suspend fun findAll(): List<LegalPerson> = dbQuery {
        LegalPersons.selectAll().map { toLp(it) }
    }

    suspend fun insert(lp: LegalPerson, ph: Phone) = dbQuery {
        LegalPersons.insert {
            it[id] = lp.id
            it[internalId] = lp.internalId
            it[companyId] = lp.companyId
            it[active] = lp.active
            it[tradeName] = lp.tradeName
            it[fantasyName] = lp.fantasyName
            it[email] = lp.fantasyName
            it[cnpj] = lp.cnpj
            it[stateRegistration] = lp.stateRegistration
            it[muninipalRegistration] = lp.muninipalRegistration
            it[address] = lp.address
        }.let {
            Phones.insert {
                it[id] = ph.id
                it[internalId] = ph.internalId
                it[phone] = ph.phone
            }
        }
    }

    private fun toLp(row: ResultRow): LegalPerson =
        Phone(
            id = row[Phones.id],
            internalId = row[Phones.internalId],
            phone = row[Phones.phone]
        ).let {
            LegalPerson(
                id = row[LegalPersons.id],
                internalId = row[LegalPersons.internalId],
                companyId = row[LegalPersons.companyId],
                active = row[LegalPersons.active],
                tradeName = row[LegalPersons.tradeName],
                fantasyName = row[LegalPersons.fantasyName],
                email = row[LegalPersons.email],
                cnpj = row[LegalPersons.cnpj],
                stateRegistration = row[LegalPersons.stateRegistration],
                muninipalRegistration = row[LegalPersons.muninipalRegistration],
                address = row[LegalPersons.address]
            )
        }
}

And my model:

// *** LEGAL PERSONS ***

data class LegalPerson(
    val id: UUID,
    val internalId: Long,
    val companyId: UUID,
    val active: Boolean,
    val tradeName: String,
    val fantasyName: String,
    val email: String,
    val cnpj: String,
    val stateRegistration: String,
    val muninipalRegistration: String,
    val address: UUID
)

object LegalPersons : Table("person.legal_person") {
    val id: Column<UUID> = uuid("id").autoIncrement().primaryKey()
    val internalId: Column<Long> = long("internal_id").autoIncrement()
    val companyId: Column<UUID> = uuid("company_id")
    val active: Column<Boolean> = bool("active")
    val tradeName: Column<String> = varchar("trade_name", 100)
    val fantasyName: Column<String> = varchar("fantasy_name", 100)
    val email: Column<String> = varchar("email", 100)
    val cnpj: Column<String> = varchar("cnpj", 18)
    val stateRegistration: Column<String> = varchar("state_registration", 20)
    val muninipalRegistration: Column<String> = varchar("municipal_registration", 20)
    val address: Column<UUID> = uuid("address")
}

// *** PHONES ***

data class Phone(
    val id: UUID,
    val internalId: Long,
    val phone: UUID
)

object Phones : Table("person.phone_legal_person") {
    val id: Column<UUID> = reference("id", LegalPersons.id).primaryKey()
    val internalId: Column<Long> = long("internal_id").autoIncrement()
    val phone: Column<UUID> = uuid("phone")
}

But I'm getting this error when I'm trying to insert data:

ERROR Application - Unhandled: POST - /api/clients/lp/
io.ktor.gson.UnsupportedNullValuesException: Receiving null values is not supported

Could anyone help? I am using DLS as opposed to DAO. I am having difficulty, since the documentation is still being made.


Solution

  • After reading a little I found out what was wrong. My service looks like this:

    suspend fun insert(lp: LegalPerson) = dbQuery {
            val ids = UUID.randomUUID()
            LegalPersons.insert {
                it[id] = ids
                it[companyId] = lp.companyId
                it[active] = lp.active
                it[tradeName] = lp.tradeName
                it[fantasyName] = lp.fantasyName
                it[email] = lp.fantasyName
                it[cnpj] = lp.cnpj
                it[stateRegistration] = lp.stateRegistration
                it[muninipalRegistration] = lp.muninipalRegistration
                it[address] = lp.address
            }
    
            Phones.batchInsert(lp.phones) { phone ->
                this[Phones.id] = ids
                this[Phones.phone] = phone.phone
    
            }
        }