【问题标题】:How to manage DB related Exceptions in Play! 2.0/Scala using Anorm如何在 Play 中管理 DB 相关异常! 2.0/Scala 使用 Anorm
【发布时间】:2012-07-15 17:34:20
【问题描述】:

我目前正在玩 Play 2.0 (Scala)。我必须承认这很有趣。我有一个与数据库操作异常有关的问题。

假设我有 Car 作为域类,并且我对其中一个字段有完整性约束,比如说 model 以便在数据库中我可以没有两 (2) 行具有相同的型号名称:

case class Car(id: Pk[Long], name: String, model: String)

我正在尝试像这样在数据库中插入一条记录:

def create(car: Car): Option[Long] = {
    DB.withConnection { implicit connection =>
      try {
          SQL("insert into cars (name, model) values ({name},{model}").on("name" -> car.name, "model" -> car.model).executeInsert()
      } catch {
          case e: Exception => {
          Logger.debug(e.getMessage())
          None
      } 
    }
}

如果我没有像前面的代码那样捕获异常,那么当我从我的控制器调用这个方法时,模型的值已经存在于数据库中,我会抛出以下异常:

com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry 'Enzo' for key 'model'

有没有办法捕获 MySQLIntegrityConstraintViolationException 而不是 Exception 以便我对可能出现的问题进行细粒度控制,然后提供更简洁的提要 -例如(在浏览器或移动设备上)返回给我的用户?

这是处理与数据库相关的操作和异常的最佳方式,还是每个人都使用的最佳实践?

提前致谢,

【问题讨论】:

    标签: playframework playframework-2.0 scala-2.8 anorm


    【解决方案1】:

    我认为您看起来像以下几行:

    import com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException
    
    catch {
      case e:MySQLIntegrityConstraintViolationException => Logger.debug("Whoops")
      case e:Exception  => {
        Logger.debug(e.getMessage())
        None
      }
    }
    

    重要提示:确保您导入的是com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException,而不是com.mysql.jdbc.exceptions.MySQLIntegrityConstraintViolationException。更准确地说,确保您的导入与堆栈跟踪中的异常匹配。

    至于最佳实践,我不知道,因为我也在玩这个框架:)。

    至于对用户的反馈......也许 Flash Scope 是一种将单行文字传达给“下一页”的好方法(例如,汽车是否成功存放)。请参阅:http://www.playframework.org/documentation/2.0/ScalaSessionFlash(向下滚动到“Flash 范围”。)

    【讨论】:

    • 我试图像这样捕获 MySQLIntegrityConstraintViolationException 异常,但它不起作用。可能是因为 MySQLIntegrityConstraintViolationException 不是案例类,因此不符合模式匹配的条件。
    • @kaffein 非大小写类可以匹配得很好,你不能解构它们,例如你不能这样做case NonCaseClass(e) =>,因为默认情况下它们没有 unapply 方法。在我的情况下,问题是不正确的导入。我导入了com.mysql.jdbc.exceptions.MySQLIntegrityConstraintViolationException 而不是com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException(注意jdbc4 包)。
    【解决方案2】:

    我在一个有点不同的游乐场工作,但据我所知,我解决了同样的问题。 我正在使用 liftweb、maven 和 scala 2.9。

    异常用 RuntimeException 包装。为了抓住它,我抓住了 RuntimeException 并检查了它的原因。如果它是违反约束的,我会做我的事,否则我会抛出异常。见以下代码:

    import com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException
    ...
      } catch {
          case e: RuntimeException => {
            e.getCause match {
              case cause: MySQLIntegrityConstraintViolationException => {
              ...
              }
              case _ => throw e
            }
          }
        }
    

    如果构建失败并出现以下错误:

    error: object mysql is not a member of package com
    

    检查 maven pom 上 mysql 包的定义。在我的情况下,它被定义为运行时范围。将其更改为编译范围允许构建成功,并且在运行时此捕获正常工作。 这是maven pom.xml中的mysql依赖部分:

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.18</version>
            <scope>runtime</scope>
        </dependency>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-12-11
      • 1970-01-01
      • 2018-07-19
      • 2014-10-24
      • 2012-04-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多