2016-05-15 55 views
0

我使用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) 

} 

这样,我不必在开始和结束时相同的元组。

+0

我认为这可能是有用的,如果你可以显示你想达到的伪代码。 – TeWu

+0

@TeWu当然,我会添加一些 – cdmckay

+0

您可以使用自定义贷款模式。例如,使用CheckAndJob [T](f:(CheckType,JobType)=> T)来确定:T =' – cchantep

回答

1

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

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

最后但并非最不重要的是你没有提及你的特定用例,但也许值得考虑在单独的withConnection块中获得2个查询结果。如果您正在使用任何集合池机制,那么几乎没有任何好处将其与连接块和独立块相同,您甚至可以灵活地使用单独的连接对数据库查询进行旁路处理。

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 
      ) 
    } 

这是最好的,如果你打算重用这个案例类多次。

+0

还有更多的方法。 PS:匿名类比我那里的元组差。 – cchantep