【问题标题】:Catching SQL error on future failure in Slick在 Slick 中捕获未来失败的 SQL 错误
【发布时间】:2016-12-04 11:22:13
【问题描述】:

下面的代码使用 Slick 3.1.x 从表中读取一行,试图捕获任何 SQL 错误。 UserDB 是表格的 Slick 表示,User 是相关对象。

此代码无法在failure 语句中编译,并出现以下错误:

类型不匹配;找到:所需单位: scala.concurrent.Future[Option[user.manage.User]]

如何解决这个问题以捕获 SQL 错误?

   def read (sk: Int): Future[Option[User]] = {
      val users = TableQuery[UserDB]
      val action = users.filter(_.sk === sk).result
      val future = db.run(action)
      future.onSuccess {
        case result =>
              if (!result.isEmpty)
                  Some(result(0))
              else
                  None
      }
      future.onFailure {   // <-- compilation error
          case e => println (e.getMessage)
          None
      }
   }

【问题讨论】:

  • onFailure 重新调用回调并返回 Unit。因此,您的整个方法返回 Unit
  • 谢谢。假设失败时我需要在日志中写入一个条目并返回None(而不是在正确读取记录时返回Some),应该采用什么方法?
  • 不要使用onFailure,而是使用Future 上可以处理异常并仍然返回某些内容的方法。
  • 我的目标是(以某种方式)捕获 SQL 异常,同时考虑到函数返回带有选项的 Future。有什么想法吗?

标签: scala playframework slick slick-3.0


【解决方案1】:

您可以使用asTry 方法将异常ex 捕获为成功结果Failure(ex) 和Success(v) 中的成功值。在您的情况下,以下应该有效。

db.run(action.asTry).map{
  case Failure(ex) => { 
         Log.error(s"error : ${ex.getMessage}") 
         None
        }
  case Success(x) => x
}

正如slick documentation 中提到的,asTry 用于管道异常恢复处理逻辑。

【讨论】:

    【解决方案2】:

    你可以使用未来的onComplete方法。

            future.onComplete{
                case Success(r) ⇒ ...
                case Failure(t) ⇒ log.error("failure in db query " + t.getMessage)
            }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-02-12
      • 2013-08-06
      • 2019-05-24
      • 2018-09-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多