使用Kotlin公开的异常处理-如何捕获唯一的违反约束的异常?

时间:2018-10-03 11:34:12

标签: kotlin kotlin-exposed

我在表中的列上添加了唯一约束。违反约束时,它将引发异常,我无法捕获并传达给用户。

Exposed: Transaction attempt #0 failed: java.sql.BatchUpdateException: Batch entry 0 INSERT INTO templates (created_at, is_deleted, name, sections) VALUES ('2018-10-03 16:31:25.732+05:30', 'FALSE', 'Template1', '[{"title":"Introduction"}]') RETURNING * was aborted: ERROR: duplicate key value violates unique constraint "templates_name_key" Detail: Key (name)=(Template1) already exists. Call getNextException to see other errors in the batch.. Statement(s): INSERT INTO templates (created_at, is_deleted, name, sections) VALUES (?, ?, ?, ?) ! org.postgresql.util.PSQLException: ERROR: duplicate key value violates unique constraint "templates_name_key" ! Detail: Key (name)=(Template1) already exists.

  • 如何使用用户可读的消息捕获此类SQL异常?
  • 是否有最佳实践来捕获这些异常?
  • 我们应该在交易内部还是外部捕获它们?有这样的必要吗?

下面是我尝试过的代码段。

return try {
    val template: TemplateSerializer = transaction {
        val newTemplate = Template.insert(request)
        TemplateSerializer.serialize(newTemplate)
    }
    Response.status(201).entity(template).build()
} catch (e: Exception) {
    if(e is SQLIntegrityConstraintViolationException) {
        resourceLogger.error("SQL constraint violated")
    } else if(e is BatchUpdateException) {
        resourceLogger.error("SQL constraint violated")
    } else
        resourceLogger.error(e.message)
    Response.status(422).entity(mapOf("error" to true, "message" to "Insertion failed")).build()
}

根本没有打印消息SQL constraint violated。尝试使用不同的Exception类进行多次捕获。没事。

发送此类通用错误消息无济于事。

2 个答案:

答案 0 :(得分:1)

暴露的抛出ExposedSQLExceptionSQLException的子类型,可以通过causeByQueries()函数访问最新执行的查询(可能导致原始异常)。可通过cause属性访问原始异常。

return try {
    val template: TemplateSerializer = transaction {
        val newTemplate = Template.insert(request)
        TemplateSerializer.serialize(newTemplate)
    }
    Response.status(201).entity(template).build()
} catch (e: Exception) {
    val original = (e as? ExposedSQLException)?.cause
    when (original) {
      is SQLIntegrityConstraintViolationException -> 
        resourceLogger.error("SQL constraint violated")
      is BatchUpdateException -> 
        resourceLogger.error("SQL constraint violated")
      else ->
        resourceLogger.error(e.message)
    }
Response.status(422).entity(mapOf("error" to true, "message" to "Insertion failed")).build()

答案 1 :(得分:0)

您可以检查sqlState

它看起来像:

try {
        userService.insertUser(user)
    } catch (e: ExposedSQLException) {

        val isUniqueConstraintError = e.sqlState == "23505"
    }

您可以从此处获取正确的错误代码:

https://www.postgresql.org/docs/10/errcodes-appendix.html