Future 上的 lazy val 是否会阻止实际的数据库调用?
Does lazy val on a Future prevent an actual database call?
我想进行这样的查询:
- 查询特定日期的记录;
- 如果 (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 次数据库,最好调用一个范围,然后在 POJO 上本地过滤以找到最新日期,对吗?
就目前而言,您的代码将同时执行 specific
和 range
,尽管它们是惰性的。考虑以下简化的片段
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))
我们看到两人都被处决了。 for-comprehension 的性质意味着它们都 运行 尽管被宣布为懒惰。如果您希望 range
仅在 specific
returns 没有结果时才执行,那么请考虑这样做
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
没有 运行。
我想进行这样的查询:
- 查询特定日期的记录;
- 如果 (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 次数据库,最好调用一个范围,然后在 POJO 上本地过滤以找到最新日期,对吗?
就目前而言,您的代码将同时执行 specific
和 range
,尽管它们是惰性的。考虑以下简化的片段
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))
我们看到两人都被处决了。 for-comprehension 的性质意味着它们都 运行 尽管被宣布为懒惰。如果您希望 range
仅在 specific
returns 没有结果时才执行,那么请考虑这样做
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
没有 运行。