将光滑的oneToMany结果映射到树格式

时间:2017-06-16 12:47:05

标签: scala playframework slick

我写了一个简单的游戏! 2使用Slick应用程序的REST。我有以下域名模型:

case class Company(id: Option[Long], name: String)

case class Department(id: Option[Long], name: String, companyId: Long)


class Companies(tag: Tag) extends Table[Company](tag, "COMPANY") {
    def id = column[Long]("ID", O.AutoInc, O.PrimaryKey)
    def name = column[String]("NAME")

    def * = (id.?, name) <> (Company.tupled, Company.unapply)
}

val companies = TableQuery[Companies]

class Departments(tag: Tag) extends Table[Department](tag, "DEPARTMENT") {
    def id = column[Long]("ID", O.AutoInc, O.PrimaryKey)
    def name = column[String]("NAME")
    def companyId = column[Long]("COMPANY_ID")

    def company = foreignKey("FK_DEPARTMENT_COMPANY", companyId, companies)(_.id)

    def * = (id.?, name, companyId) <> (Department.tupled, Department.unapply)
}

val departments = TableQuery[Departments]

这是我查询所有相关部门所有公司的方法:

override def findAll: Future[List[(Company, Department)]] = {
    db.run((companies join departments on (_.id === _.companyId)).to[List].result)
}

不幸的是,我想以树JSON格式显示数据,所以我必须构建查询,让所有公司都有部门,并以某种方式将它们映射到CompanyDTO,如下所示:

case class CompanyDTO(id: Option[Long], name: String, departments: List[Department])

你知道什么是最好的解决方案吗?我应该使用JSON格式化程序映射列表[(公司,部门)]还是应该更改我的查询以使用CompanyDTO?如果是这样,我如何将结果映射到CompanyDTO?

1 个答案:

答案 0 :(得分:0)

我知道的一对多关系已知在RDBMS中的一个查询中被提取。在避免n + 1问题时你可以做的最好的事情就是在2个查询中完成它。在这里,你的情况如何:

for {
  comps <- companies.result
  deps <- comps.map(c => departments.filter(_.companyId === c.id.get))
               .reduceLeft((carry,item) => carry unionAll item).result
  grouped = deps.groupBy(_.companyId)
} yield comps.map{ c => 
  val companyDeps = grouped.getOrElse(c.id.get,Seq()).toList
  CompanyDTO(c.id,c.name,companyDeps)
}

此查询中有一些固定的部分,您将及时发现。这使它成为抽象的一个很好的候选者,你可以重复使用它来获取一般的一对多关系。