与未来的隐含转换

时间:2017-03-02 16:34:57

标签: scala future implicit-conversion

我在从DB模型到APP模型的隐式转换方面遇到了问题:

  override implicit def dbBook2AppBook(book: Book): BookApp = {
      val author = Await.result(authRep.getById(book.authID),1 seconds)
      BookApp(book.id.get, book.title, 
              AuthorApp(author.get.id,author.get.name,author.get.surname), book.available)
  }

基本上我想将Book转换为BookApp:

case class BookApp(id: Int,
                   title: String,
                   author: AuthorApp,
                   var available: Boolean)

case class Book(id: Option[Int] = None, title: String, authID: Int, available: Boolean)

正如您可以看到我的Book类具有作者ID,我希望我的BookApp内部包含AuthorApp对象。我需要做的是从数据库中获取,同时从Book进行转换。从数据库到authRep: AuthorReposiotory我获得Future[Author]

我的问题是,如果有更好的方法从convertion获取BookApp而无需使用等待Author对象?有什么建议?

修改

对于Jon Anderson"的答案,我无法从Future[Book]转换为Future[BookApp],因为当我获得多行从数据库我收到Future[Seq[Book]],然后转换不起作用。附加信息,我仍然在整个应用程序中保留Future,因为当我进行转换时,我会做这样的事情:

  def findBooks(title: Option[String], authorName: Option[String], 
                authorSurname: Option[String], available: Option[Boolean])
                : Future[Seq[BookApp]] = {
    bookRep.findBooks(title,authorName,authorSurname,available)
                      .map(x => x.map( y => y: BookApp))
  }

因此,转换是按对象按地图完成的,但仍然返回已转换的未包装对象。主要问题是等待转换,所以主要的问题是,我该怎样摆脱它?

2 个答案:

答案 0 :(得分:1)

当你发现以下类型时:你可以

首先,忘记在您的设计中使用隐含,直到您更熟悉这些语言,他们不会在这里帮助您。 (并忘记隐式转换永远......)

这里可能采用的一种方法是在Future上下文中保持工作{/ 1}}。

可以使用dbBook2FutureAppBook(book: Book): Future[BookApp]Future[Seq[Book]]Future[Seq[Bookapp]]转换为Future#flatMap

Future.sequence

这回答了您关于val fsb: Future[Seq[Book]] = ... val fsa: Future[Seq[Bookapp]] = fsb.flatMap { books => Future.sequence(books.map(dbBook2FutureAppBook)) } 的问题,但请注意,这会在Future中为每本书发出一次数据库查询,这是一个糟糕的主意。您可能希望手动编写Future[Seq[Book]]查询。

答案 1 :(得分:0)

您应该将所有未来保留到应用层。在这种情况下,for-comprehension很有效......

override implicit def dbBook2AppBook(bookFuture: Future[Book]): Future[BookApp] = { 
    for {
       book <- bookFuture
       author <- authRep.getById(book.authID)
       //any other futures needed to create APP model here...
    } yield {
        BookApp(book.id.get, book.title, AuthorApp(author.get.id,author.get.name,author.get.surname), book.available)
    }
}