我写了一个简单的游戏! 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?
答案 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)
}
此查询中有一些固定的部分,您将及时发现。这使它成为抽象的一个很好的候选者,你可以重复使用它来获取一般的一对多关系。