【问题标题】:Does lazy val on a Future prevent an actual database call?Future 上的惰性验证是否会阻止实际的数据库调用?
【发布时间】:2019-11-29 06:26:38
【问题描述】:

我想进行这样的查询:

  1. 查询特定日期的记录;
  2. 如果 (1) 失败,则查询某个日期范围内的记录,取最后一个日期。

我现在的处理方式是:


lazy val specific: Future[Option[QueryResponse]] = // some database call

lazy val range: Future[Option[QueryResponse]] = 
  // some database call returning Future[Seq[QueryResponse]]
  .map { qrs =>
    if (qrs.nonEmpty) Some(qrs.maxBy(_.date)(_ compareTo _))
    else None
  }

for {
  s <- specific  
  r <- range
} yield {
 (s, r) // match on combination of Some/None
}

两个问题:

  1. 惰性会阻止评估数据库调用吗?我希望尽可能少地拨打电话。这与其他任何问题一样都是语言问题。
  2. 认识到无论如何都必须进行 1 次数据库调用,最好对一个范围进行调用,然后在 POJO 上进行本地过滤以查找最新日期,对吗?

【问题讨论】:

    标签: scala future


    【解决方案1】:

    就目前而言,您的代码将同时执行specificrange,尽管它们很懒惰。考虑以下简化的 sn-p

      lazy val specific = Future(Some("specific"))
      lazy val range = Future(Some("range"))
    
      (for {
        s <- specific
        r <- range
      } yield {
        (s, r)
      }).foreach(println)
    

    哪个输出

    (Some(specific),Some(range))
    

    我们看到两者都被执行了。理解的性质意味着尽管被宣布为懒惰,但他们俩都跑了。如果您希望 range 仅在 specific 没有返回结果时执行,请考虑这样做

    specific.flatMap {
        case Some(v) => Future(Some(v), None)
        case _ => range.map {
          case Some(v) => (None, Some(v))
          case _ => (None, None)
        }
      }.foreach(println)
    

    哪个输出

    (Some(specific),None)
    

    我们看到range 的地方没有运行。

    Scalaz 将问题简化为

    import scalaz._
    import scalaz.std.scalaFuture.futureInstance
    
    OptionT(specific).orElse(OptionT(range)).map(println)
    

    哪个输出

    specific
    

    这意味着range 没有运行。

    【讨论】:

    • 这是不对的。 range 只有在specific 成功时才会执行。
    • @Tim 如果特定返回 Future(None) 范围仍将运行。
    • 是的,我越看这个越不明白!我假设数据库故障会使Future 失败,但也许它只是返回None
    • 这很巧妙。谢谢你。关于这是否是“正确”方法的任何评论?过滤范围和查找最新日期是否会更有效,因为数据库调用会以任何一种方式进行?我假设对第一个请求失败的统计可能性进行某种研究会为这个决定提供信息。
    • @franklin 如果不实际观察它在现实世界中的表现,很难判断。我的建议是尝试使用 range,如果您发现性能不足,请添加优化。
    猜你喜欢
    • 2019-08-23
    • 1970-01-01
    • 1970-01-01
    • 2020-02-09
    • 2010-10-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-11
    相关资源
    最近更新 更多