我在从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))
}
因此,转换是按对象按地图完成的,但仍然返回已转换的未包装对象。主要问题是等待转换,所以主要的问题是,我该怎样摆脱它?
答案 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)
}
}