如何从封闭传递数据而不重复自己

时间:2016-05-15 17:39:48

标签: scala playframework playframework-2.0 anorm

我使用Play 2和Anorm来管理数据库访问。我发现自己正在做的一个常见模式是:

val (futureChecklists, jobsLookup) =
  DB.withConnection { implicit connection =>

    val futureChecklists = futureChecklistRepository.getAllHavingActiveTemplateAndNonNullNextRunDate()

    val jobsLookup = futureChecklistJobRepository.getAllHavingActiveTemplateAndNonNullNextRunDate()
        .groupBy(_.futureChecklist.id)
        .withDefaultValue(List.empty)

    (futureChecklists, jobsLookup)

  }

这似乎有点奇怪,因为我必须重复自己。如果我在外部范围内需要几个变量,那么它也会变得有点不守规矩,但我不想让连接保持打开状态。

是否有一种简单的方法可以将这些信息传回去,而无需使用var

我想要的是:

val futureChecklists
val jobsLookup

DB.withConnection { implicit connection =>

  futureChecklists = futureChecklistRepository.getAllHavingActiveTemplateAndNonNullNextRunDate()

  jobsLookup = futureChecklistJobRepository.getAllHavingActiveTemplateAndNonNullNextRunDate()
      .groupBy(_.futureChecklist.id)
      .withDefaultValue(List.empty)

}

这样我在开始和结束时都没有相同的元组。

2 个答案:

答案 0 :(得分:1)

恐怕没有简单的方法可以不复制元组声明,但var绝对不是解决问题的方法。

你提到过多个变量作为一个元组返回时变得奇怪和困难。这确实会变得非常棘手并且容易出错,尤其是最终你会得到具有相同参数类型的大型N元组。在那种情况下,我会考虑使用一个专用的包含case class,您可以在其中按名称引用变量,而不是按元组中的位置引用变量。另一个好处是,您可以将整个容器分配给变量并以自然方式引用它。

最后但并非最不重要的是,您没有提及您的特定用例,但可能值得考虑在单独的withConnection块中获得2个查询结果。如果您正在使用任何集合池机制,那么使用连接块和单独的块几乎没有任何好处,甚至可以灵活地使用单独的连接来简化数据库查询。

答案 1 :(得分:0)

我想出了三种方法:

立即返回元组

val (users, posts) =
  DB.withConnection { connection => (
    connection.getUsers,
    connection.getPosts
  )}

我认为这对于简单代码和少量val来说是可以的。对于更复杂的代码和更多val s,这可能容易出错。有人可能会在赋值的一侧意外地更改元组中元素的顺序,并将数据分配给错误的val(仅当编译器也会导致类型不匹配时才由编译器报告)。

使用匿名类

val dbResult =
  DB.withConnection { connection =>
    new {
      val users = connection.getUsers
      val posts = connection.getPosts
    }
  }

如果您想使用usersposts个变量代替dbResult.usersdbResult.posts,您可以:

import dbResult._

这个解决方案有点异国情调,但效果很好而且很干净。

用例类

首先为您的返回值定义案例类:

case class DBResult(users: List[User], posts: List[Post])

然后使用它:

val DBResult(users: List[User], posts: List[Post]) =
  DB.withConnection { connection =>
    DBResult(
              users = connection.getUsers,
              posts = connection.getPosts
            )
  }

如果您打算多次重复使用此案例类,这是最好的。