天道酬勤,学无止境

Scala Playframework 并非所有数据库查询都被执行(Scala Playframework not all DB queries get executed)

问题

我正在通过 HTTP Post Request 向我的 Playframework 后端发送一个 Json。

在我的后端,我将 Json 验证为模型。 之后,我想将模型中的条目保存到我的数据库中。

   def parseJSON: Action[AnyContent] = Action.async {
       request =>
         Future {
           request.body.asJson.map(_.validate[MyModel] match {
             case JsSuccess(items, _) =>
               itemsToDBController.saveItems(items)
               Ok("Success")
             case JsError(err) =>
               println(err)
               BadRequest("Json Parse Error")
           }).getOrElse(BadRequest("Error"))
         }
     }

一个项目由几个对象组成。 要将所有对象保存到我的数据库中,我需要获取一些值。 因此,我使用了 for(..) yield(...):

   def saveItems(items: MyModel) = {
       items.SomeObject.map(obj => {
         if (obj.value1.isDefined &&
           obj.value2.isDefined ) {
           val result = for (
             value1Exists <- value1DTO.checkExists(obj.value1.name);
             value1Entry <- getOrCreateValue1(value1Exists, obj);
             value2Exists <- value2DTO.checkExists(obj.value2.name);
             value2Entry <- getOrCreateValue2(value1Exists, obj)
            ) yield(value1Entry, value2Entry)

           result.map({
             case (value1Entry, value2Entry) => {
               insertAllValue3(value1Entry, value2Entry)
               Future.successful()
             }
             case _ => Future.failed(new Exception("Not all entries defined"))
           })
         }
         else {
             Future.successful("Not all objects defined - skipping")
         }
       })
     }

我的问题是,在所有result.map({...})开始之后,我的 parseJSON Action returns 200 - OK 。 但并非所有相关项目都存储到我的数据库中。 似乎在200 - OK一切都停止了,甚至没有抛出错误。 我不想在我的操作中使用 Await.result 或任何阻塞。

提前致谢

回答1

您通过调用itemsToDBController.saveItems(items)开始计算,然后立即使用Ok("Success")返回结果。 因此,如果请求完成,则可能会在请求后引发异常。

要解决此问题,您需要在itemsToDBController.saveItems帮助下将Future.sequence结果从List[Future[T]]Future[List[T]] 。 然后在返回的未来调用map方法。 在此Future上调用recover以查找引发了哪个错误:

def parseJSON: Action[AnyContent] = Action.async { request =>
  request.body.asJson
    .map(_.validate[MyModel] match {
      case JsSuccess(items, _) =>
        Future
          .sequence(itemsToDBController.saveItems(items))
          .map(_ => Ok("Success"))
          .recover {
            case e: Exception => BadRequest(e.getMessage())
          }

      case JsError(err) =>
        println(err)
        Future.successful(BadRequest("Json Parse Error"))
    })
    .getOrElse(Future.successful(BadRequest("Error")))
}

更新

为了在一个事务中运行所有插入,您应该结合DBIOAction而不是Future 。 例如,您将checkExists(name)重写为:

def checkExists(name: String): DBIO[Boolean] = {
  Objects.filter(obj => obj.name === name).exists
}

getOrCreateValue(exists, obj)为:

def getOrCreateValue(exists: boolean, obj: Object): DBIO[Object] = {
  if (exists) {
    Objects.filter(o => o.name === name).result.head
  } else {
    (Objects returning Objects.map(_.id) into ((o, id) => o.copy(id = Some(id)))) += obj
  }
}

现在您可以通过以下方式在单个事务中运行它:

def saveItems(items: MyModel) = {
  val insertActions = items.SomeObject.map(obj => {
    if (obj.value1.isDefined && obj.value2.isDefined) {
      val result = for {
        value1Exists <- value1DTO.checkExists(obj.value1.name);
        value1Entry <- getOrCreateValue1(value1Exists, obj);
        value2Exists <- value2DTO.checkExists(obj.value2.name);
        value2Entry <- getOrCreateValue2(value1Exists, obj)
      } yield (value1Entry, value2Entry)

      result.flatMap({
        case (value1Entry, value2Entry) => {
          insertAllValue3(value1Entry, value2Entry) // This also returns instance of `DBIOAction`
        }
        case _ =>
          DBIO.failed(new Exception("Not all entries defined"))
      })
    } else {
      DBIO.successful("Not all objects defined - skipping")
    }
  })
  db.run(DBIO.sequence(inserActions).transactionally)
}

有关如何使用 DBIO 操作的信息,请查看此官方文档

受限制的 HTML

  • 允许的HTML标签:<a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • 自动断行和分段。
  • 网页和电子邮件地址自动转换为链接。

相关推荐
  • 如何从sql中获取数据并使用带有playframework的scala的if条件测试结果?(How to fetch the data from sql and test the result using if conditions using scala with playframework?)
    问题 我有一个控制器 => @Singleton class NewBillingMonthController @Inject() (implicit cacheService: CacheService, repository: NewBillingRoleRepository, contexts: Contexts, securityService: SecurityService) extends BaseController { def getAll(implicit queryParams: QueryParams): Action[AnyContent] = securityService.authenticate() { implicit request => withErrorRecovery { req => toJson { repository.getAll(request.user.loginName) repository.getUser() } // 如果我定义了 sql,此控制器调用存储库 这显示存储库=> newBillingRepository.scala=> class NewBillingRoleRepository @Inject() (val queryHandler: QueryHandler, val contexts
  • 使用 Playframework Scala @select 模板 - onchange 事件(Using the Playframework Scala @select template - onchange event)
    问题 我正在将 playframework 2.0 与 Scala 一起使用,但@select 模板面临许多问题。 所以我有一个@select 字段作为表单的一部分(表单在这里不应该很有趣): @select( Form("<variable of select 1>"), options = options(<call of function which returns a list>), '_default -> "--- stupid select templates ---", '_error -> Form.globalError ) 现在我有另一个选择。 关于这一点很重要的是 - 我想从一个函数中填充它,该函数获取第一个 @select 的实际值作为参数。 @select( Form("<other name of variable>"), options = options(<function(<variable of select 1>)>), '_default -> "--- stupid select templates ---", '_error -> Form.globalError ) 所以我真正需要的是@select 字段的某种“onchange”环境。 另一个问题是,playframework 无法读取@select 的“'_default”值
  • playframework-包javax.persistence不存在(playframework - package javax.persistence does not exist)
    问题 我在模型中使用本教程http://vimeo.com/58969923#(来自playframework.com页面的一个教程)时遇到问题: 播放2.2.1 / jcirs / app / models / MedicalIncident.java 公共类MedicalIncident扩展了模型{} 我正在尝试使用实体。 为此,我必须导入:javax.persistence。*和play.db.ebean。*,但找不到它们。 错误是 软件包javax.persistence不存在 我应该怎么办? 使用任何其他数据库引擎? 还是应该下载一些依赖项。 我想采用Playframework的最佳方法。 请帮忙。 我的配置application.conf: db.default.driver=org.h2.Driver db.default.url="jdbc:h2:mem:play" ebean.default="models.*" 堆栈跟踪: [jcirs] $ run 8081 --- (Running the application from SBT, auto-reloading is enabled) --- [info] play - Listening for HTTP on /0:0:0:0:0:0:0:0:8081 (Server started, use Ctrl
  • Playframework JSON 解析 - 空指针异常 - 当数组存在时(Playframework JSON parsing - Null pointer exception - when array is present)
    问题 我正在使用 playframework 进行 JSON 解析,并且面临以下 NullPointerException: 我的数据模型如下: case class SearchLikeThisResult(total: Int, max_score: Double, hits: Seq[Hits]) case class Hits( index: String, typ: String, id: String, score: Double) 我的读者如下: object SearchLikeThisHits { import play.api.libs.functional.syntax._ implicit val searchLikeThisResult: Reads[SearchLikeThisResult] = ( (JsPath \ "total").read[Int] and (JsPath \ "max_score").read[Double] and (JsPath \ "hits").read[Seq[Hits]] )(SearchLikeThisResult.apply _) implicit val hitsReads: Reads[Hits] = ( (JsPath \ "_index").read[String] and (JsPath \ "
  • 我的 PlayFramework Action 在 Future 准备就绪之前返回,如何更新网页组件?(My PlayFramework Action returns before a Future is ready, how do I update a web page component?)
    问题 我有一个调用 MongoDB 并获得Future[Seq[Document]]结果的 Scala PlayFramework 函数。 在地图缩放/平移事件之后,通过 xhttp/GET 从网页上的 JavaScript 调用此 Play Action函数。 我在 Play 端的 Action 方法在 Future 的onComplete/Success执行之前返回。 所以我正在寻找一种在 Scala Future 的 onComplete/Success 触发时调用 JavaScript 函数来获取数据的方法。 我该怎么做,还是我看错了? 这是有问题的代码。 def rect(swLon: Float, swLat: Float, neLon: Float, neLat: Float) = Action { val sb = new StringBuilder() sb.append("<tt>boundingBox: swLon=" + swLon + ", swLat=" + swLat + ", neLon=" + neLon + ", neLat=" + neLat + "</tt>") if (oDb.isDefined) { val collection: MongoCollection[Document] = oDb.get.getCollection
  • 信任 Java Playframework 2.2 中的所有 SSL 证书(Trust all SSL certificates in Java Playframework 2.2)
    问题 我正在尝试使用以下函数在 Play Framework 中调用网络服务(具有自签名 SSL 证书): public static play.libs.F.Promise<Result> webcall() { String feedUrl = "https://10.0.1.1/client/api"; final play.libs.F.Promise<Result> resultPromise = WS.url(feedUrl).get().map( new Function<WS.Response, Result>() { public Result apply(WS.Response response) { return ok("Feed title:" + response.asJson().findPath("title").toString()); } } ); return resultPromise; } 它在日志中抛出以下错误, [error] play - Cannot invoke the action, eventually got an error: java.net.ConnectException: General SSLEngine problem to https://10.0.1.1/client/api [error]
  • 如何使用 Scala 中的 playframework 将文件上传到数据库(How to upload a file to the database using playframework in Scala)
    问题 使用 Play!2 和 Scala 处理文件上传到数据库的推荐方法是什么? 回答1 根据您的特定要求,MongoDB 的 GridFS 将以比任何关系数据库和文件系统更高效和可扩展的方式为您存储文件。 http://www.mongodb.org/display/DOCS/GridFS Play 有很多支持 GridFS 的 MongoDB 插件。
  • 如何使用 Mill 构建工具而不使用 SBT 来设置 PlayFramework 项目?(How do I set up a PlayFramework project using the mill build tool, and without using SBT?)
    问题 以下是我目前如何设置 PlayFramework 项目以与mill一起使用: 创建一个文件夹: /path/to/play-scala-seed-mill/并 cd 进入该文件夹。 根据 PlayFramework 支持的官方文档中的说明,在此文件夹中创建一个build.sc文件。 这是我不喜欢的部分:为了创建文件夹结构并为 Play 添加文件,我按照 Play 的官方文档运行sbt new playframework/play-scala-seed.g8 。 有没有更mill -ish的方式来做到这一点? 作为上述命令的结果,从/path/to/play-scala-seed-mill/下创建的新文件夹中删除 SBT 相关代码。 使用命令mill mill.scalalib.GenIdea/idea创建一个想法项目。 如何在不使用 SBT 的情况下执行此操作? 回答1 在没有任何SBT 的情况下开始一个新的Mill项目,我可以想到这两种可能性: 白手起家 我通常从一个空文件夹开始,然后添加一个空的build.sc 。 设置几个需要的文件夹和配置有时比删除模板中不需要的所有内容要快。 创建您自己的 Giter8 模板 如果您启动了很多项目 - 您可以创建自己的Giter8模板。 这是直截了当的,还有一个无需 sbt 即可工作的命令行工具。 例如: g8
  • 执行异常AskTimeoutException:游戏框架超时(Execution exceptionAskTimeoutException: Timed out playframework)
    问题 我正在从 Ajax 调用一个方法......和 ​​PlayFramework 2.1.3 $.ajax({ type: "POST", contentType: "application/json; charset=utf-8", dataType: "json", url: "/examplefoo", data: JSON.stringify(exampleArray), success: function(data) { doSomething(); }, error: function(e) { console.log(e); } }); 在 Application.java 上 我调用了一个进行大量计算的方法,这花费了很多时间...... @BodyParser.Of(play.mvc.BodyParser.Json.class) public static Result examplefoo() throws SQLException, IOException { DAOFoo fooDAO = new DAOFoo(); result = fooDAO.methodOfHugeComputation(); return ok(play.libs.Json.toJson(result)); } 经过 50 分钟或多或少的处理后,我收到了此超时错误: [error
  • Scala Playframework 发送文件(Scala Playframework send file)
    问题 我有一个数据字符串,它是从数据库中的数据中获取的。 我想将它发送给用户,但不创建文件的本地副本,例如 Ok(MyString).as("file/csv") 但它不起作用。 我该怎么做? 回答1 您可以通过使用chunked和Enumerator来做到这一点。 我还使用withHeaders将Result的内容类型和处置指定为“附件”,以便客户端将其解释为要下载的文件(而不是在浏览器本身中打开)。 import play.api.libs.iteratee.Enumerator val myString: String = ??? // the String you want to send as a file Ok.chunked(Enumerator(myString.getBytes("UTF-8")).andThen(Enumerator.eof)) .withHeaders( "Content-Type" -> "text/csv", "Content-Disposition" -> "attachment; filename=mystring.csv" ) 这可能不会立即编译,具体取决于您从数据库中获取的类型。 想想看,这也应该有效(没有Enumerator ): Ok(myString).withHeaders( /* headers from above */
  • 我可以将sbt的apiMappings设置用于托管依赖项吗?(Can I use sbt's `apiMappings` setting for managed dependencies?)
    问题 我想用sbt生成的ScalaDoc链接到外部库,在sbt 0.13中,我们有autoAPIMappings ,应该为声明其apiURL库添加这些链接。 但是在实践中,我所使用的库中没有一个在其pom / ivy元数据中提供此功能,我怀疑其中一些库永远不会这样做。 apiMappings设置应该可以帮助您解决此问题,但是将其键入为Map[File, URL] ,因此适合为非托管依赖项设置文档url。 托管依赖项被声明为sbt.ModuleID实例,并且不能直接插入该映射中。 我可以用某种方式将URL与托管依赖项相关联的方式填充apiMappings设置吗? 一个相关的问题是:sbt是否提供从ModuleID获取File的惯用方式? 我想我可以尝试评估一些类路径并获取File以尝试将它们映射到ModuleID但是我希望有一些更简单的方法。 注意:这与https://stackoverflow.com/questions/18747265/sbt-scaladoc-configuration-for-the-standard-library/18747266有关,但该问题因链接到标准库的scaladoc而有所不同,为此,有一个众所周知的File scalaInstance.value.libraryJar ,在这种情况下不是这种情况。 回答1 通过执行以下操作
  • Playframework 2.1 找不到 javax.persistence 和 play.db(Playframework 2.1 doesn't find javax.persistence and play.db)
    问题 我对使用 play 框架(2.1 版)创建实体的 Scala 教程有问题。 我正在尝试做: import java.util._ import javax.persistence._ import play.db.jpa._ 但是当我编译时,它告诉我 javax.persistence 不存在, play.db 也不存在。 我想这是版本问题,因为在我看来,实际的 yabe-tutorial 有点旧。 你知道有什么网站有很好的解释和例子吗? 谢谢你的帮助! 回答1 当您使用 Scala 时,您可以看看 Slick,它似乎是 Play 的未来数据库持久性框架,而放弃教程中的那个。 如果您有jdbc作为依赖项,请查看您的 Build.scala。 这是我的依赖 val appDependencies = Seq( jdbc, "mysql" % "mysql-connector-java" % "5.1.22", "com.typesafe" % "slick_2.10.0-RC1" % "0.11.2", "org.mindrot" % "jbcrypt" % "0.3m" ) 回答2 build.scala现在已弃用。 在 play 2.2.x 添加到 build.sbt: libraryDependencies ++= Seq( javaJdbc, javaEbean)
  • 在 playframework 2.4 中添加带有 json 转换器的可选属性(Add optional property with json transformers in playframework 2.4)
    问题 我无法理解,如何使用 json 转换器添加可选属性。 我想合并两个没有或有动态属性列表的 json 对象(列表和日历)(例如没有owner ): calendar1 = {id:1, name: "first", description:"my first calendar", owner: 1} calendar2 = {id:2, name: "second", owner: 1} list = [{id: 1, settings: []}, {id: 2, settings: []}] 结果必须是 {calendars: [ {id:1, name: "first", description:"my first calendar", settings: []}, {id:2, name: "second", settings: []} ] } 回答1 我将假设以下 json 树 val calendar1 = Json.parse("""{"id":1, "name": "first", "description":"my first calendar", "owner": 1}""") val calendar2 = Json.parse("""{"id":2, "name": "second", "owner": 1}""") 您需要为每个日历添加设置
  • scala 代码导致 eclipse 中 playframework-2.0 出错(scala code causes error in eclipse for playframework-2.0)
    问题 我正在 eclipse 上尝试playframework-2.0的todolist tutorial 。我对代码进行了eclipsified并将其导入,以便eclipse(helios)可以正确检测播放 api。但是我在scala部分遇到了问题 我更新了 eclipse 以获得 scala ide 插件。仍然 eclipse 在旁边显示错误标记 return ok(views.html.index.render(Task.all(),taskForm)); 错误弹出框显示views.html.index cannot be resolved to a type 知道如何解决这个问题吗? 回答1 查看 Scala IDE 教程中的设置和使用 Play 框架。 如有任何问题,请在 scala-ide-user ML 上找我们。 回答2 就我而言,解决方案是将 /target/scala-2.10/src_managed/main 文件夹添加到类路径中。 回答3 我能够通过再次使项目黯然失色来摆脱这个警告 play eclipse 或者 activator eclipse # If you use activator
  • Playframework scala 如何创建临时变量(Playframework scala howto create temp variable)
    问题 嗨所以我有一个while循环: @for(i <- 0 until consoles.size) { ... Do something ... Add records to a column } 但是我想添加一个变量并根据发生的情况将其添加到不同的组。 例如: @var column = 0; @for(i <- 0 until consoles.size) { @if(consoles[i].groupname != consoles[i - 1].groupname) { column = column + 1; } ... Do something ... Add records to a column } 这可能吗。 我发现的唯一一件事是传入一个变量并使用它,但我不想这样做,虽然它只是一个 int 所以不会向客户端发送更多信息我更喜欢如果我可以在Scala模板? 任何帮助,将不胜感激。 回答1 在您的情况下,有更好的解决方案。 由于模板在 Scala 中,您可以使用 Collections API 中的一些很棒的方法,例如 groupBy : @myList.groupBy(_.groupname).map { case (group, items) => { <h2>@group</h2> @items.map { item => ... } } } Scala
  • Scala、PlayFramework、Mockito、ExecutionContext null(Scala, PlayFramework, Mockito, ExecutionContext null)
    问题 按照这个答案:https://stackoverflow.com/a/30806548/4496364 我在我的项目中使用 Play 的 ExecutionContext。 最近需要使用 Mockito 来测试 Play 中的一些服务。 所以,这是它的简化版本: import scala.concurrent.{ Future, ExecutionContext } import play.api.libs.concurrent.Execution.Implicits.defaultContext case class Model(id: Int, name: String) trait DAO { def findAll(implicit ec: ExecutionContext): Future[List[Model]] } class Service(dao: DAO) { def findAll: Future[List[Model]] = dao.findAll } 测试: import play.api.libs.concurrent.Execution.Implicits.defaultContext // doesn't work when different ExecutionContext // import scala.concurrent
  • 如何编写数据库调用的单元测试(How to write unit tests for database calls)
    问题 我临近一个新项目的开始,而且(我真是气死了!)我有史以来第一次尝试将单元测试包括在我的项目中。 我在自己设计一些单元测试时遇到了麻烦。 我有几种方法很容易测试(传递两个值并检查期望的输出)。 我的代码的其他部分正在做更复杂的事情,例如对数据库运行查询,我不确定如何对其进行测试。 public DataTable ExecuteQuery(SqlConnection ActiveConnection, string Query, SqlParameterCollection Parameters) { DataTable resultSet = new DataTable(); SqlCommand queryCommand = new SqlCommand(); try { queryCommand.Connection = ActiveConnection; queryCommand.CommandText = Query; if (Parameters != null) { foreach (SqlParameter param in Parameters) { queryCommand.Parameters.Add(param); } } SqlDataAdapter queryDA = new SqlDataAdapter(queryCommand); queryDA
  • 为什么我的 PlayFramework 应用程序超时很长?(Why do I get a very long timeout in my PlayFramework app?)
    问题 我已经创建了一个可用的应用程序,但有时当我更改内容并点击浏览器中的“重新加载”按钮时,应用程序需要永远超时(300000 毫秒或5 分钟! )。 之后,我在浏览器中收到以下异常: java.util.concurrent.TimeoutException: Futures timed out after [300000 milliseconds] scala.concurrent.impl.Promise$DefaultPromise.ready(Promise.scala:219) scala.concurrent.impl.Promise$DefaultPromise.result(Promise.scala:223) scala.concurrent.Await$$anonfun$result$1.apply(package.scala:111) scala.concurrent.BlockContext$DefaultBlockContext$.blockOn(BlockContext.scala:53) scala.concurrent.Await$.result(package.scala:111) play.forkrun.ForkRun$$anonfun$askForReload$1.apply(ForkRun.scala:123) play.forkrun
  • 用于真实 Web 项目的 Scala-JS [关闭](Scala-JS for real web project [closed])
    问题 关闭。 这个问题是基于意见的。 它目前不接受答案。 想改善这个问题吗? 更新问题,以便通过编辑这篇文章用事实和引文来回答问题。 4年前关闭。 改进这个问题 有人在真实的 web 项目中使用过Scala-JS而不仅仅是在隔离环境中使用纯JavaScript替换吗? 我想尽可能多地使用 Scala(我希望我可以)。 似乎Scala-JS声称是我可以(现在)或将来使用的库。 这就是为什么我对小型工作解决方案感兴趣,以引导(如Scala-JS PlayFramework应用程序)。 可以证明Scala-JS可以用于实际 Web 开发工作的解决方案/示例。 我问是因为到目前为止我发现的关于Scala-JS内容几乎没有真正使用它。 问:一些例子/证明它可以在实际项目中使用吗? 更新(1年后): 例如,有大量的TypeScript示例.. 这就是我说“示例”和“真实 Web 项目”时的意思。 还有很多在线培训。 如果我在 Google 中查询:“typescript github angular”,它会返回172 000 pages 。 ScalaJS缺乏这一切,但不幸的是。 但它有一些:'“scala-js”github angular ' - 4 980 匹配。 但到目前为止大部分都是“早期开发”,“没有商业支持” 那个看起来很有希望:https://github.com
  • 在 Mac OSX 上运行 IntelliJ 中的第一个 playframework 示例(running the first example of playframework in IntelliJ on a Mac OSX)
    问题 在我的新mac OSX 10.8.3中,我安装了scala 2.10.0,play 2.1.0和IntelliJ12,创建了一个play工程如下: #install brew > ruby -e "$(curl -fsSL https://raw.github.com/mxcl/homebrew/go)" > brew --version 0.9.4 # update brew database > cd $(brew --prefix) > brew update > cd $(brew --prefix) && git pull --rebase # get scala 2.10.0 > brew versions scala 2.10.1 git checkout 79dc6f1 Library/Formula/scala.rb 2.10.0 git checkout 8ca07aa Library/Formula/scala.rb 2.9.2 git checkout 8896425 Library/Formula/scala.rb ... > git checkout 8ca07aa Library/Formula/scala.rb # 2.10.0 > brew install scala > scala -version Scala code runner