如何建立与SLICK的反向关系模型? [英] How to model an inverse relationship with Slick?
问题描述
我正尝试在SLICK 3.1.0-M1中为多对多关系建模
这是SLICK文档的示例
// Definition of the SUPPLIERS table
class Suppliers(tag: Tag) extends Table[(Int, String, String, String, String, String)](tag, "SUPPLIERS") {
def id = column[Int]("SUP_ID", O.PrimaryKey) // This is the primary key column
def name = column[String]("SUP_NAME")
def street = column[String]("STREET")
def city = column[String]("CITY")
def state = column[String]("STATE")
def zip = column[String]("ZIP")
// Every table needs a * projection with the same type as the table's type parameter
def * = (id, name, street, city, state, zip)
}
val suppliers = TableQuery[Suppliers]
// Definition of the COFFEES table
class Coffees(tag: Tag) extends Table[(String, Int, Double, Int, Int)](tag, "COFFEES") {
def name = column[String]("COF_NAME", O.PrimaryKey)
def supID = column[Int]("SUP_ID")
def price = column[Double]("PRICE")
def sales = column[Int]("SALES")
def total = column[Int]("TOTAL")
def * = (name, supID, price, sales, total)
// A reified foreign key relation that can be navigated to create a join
def supplier = foreignKey("SUP_FK", supID, suppliers)(_.id)
}
val coffees = TableQuery[Coffees]
我希望能够将供应商的案例类编写为
case class Supplier(
id: Int,
name: String,
street: String,
city: String,
state: String,
zip: String,
coffees: List[Coffee]
)
我正在试着做这件事,但目前我做不到。我还希望有一些方法,允许以级联模式更新内部的Supplier对象和Coffee对象。
推荐答案
答案很简单:您无法。Slick
是FRM
(函数关系映射),简单地说,它将关系元组映射到Scala对象(通常是tuples
/case classes
)。您想要实现的目标在标准SQL中不容易表达,因此不能直接在Slick
中表达。我在这里特别提到标准SQL--因为我知道有些数据库允许您将某些字段分组并聚合到列表或数组中--然而,这远远超出了标准SQL的范围,老实说,我甚至不确定您在一般情况下是否能够做到这一点。
您可以在某种程度上模仿上面的查询,方法是对两个表之间的SELECT
执行JOIN
,然后对结果进行分组(这里重要的是-Results,我不是在说SQLGROUP BY
),以获得coffees
列表。
可能如下所示:
首先-将您的表定义映射到Case类-因此不是:
class Coffees(tag: Tag) extends Table[(String, Int, Double, Int, Int)]
执行此操作:
class Coffees(tag: Tag) extends Table[Coffee]
并可能将现有的Supplier
case类重命名为SupplierComposite
或其他任何名称,这意味着它并不严格地映射到db表,而是两个不同表的组合。
与Supplier
相同。
这并不是严格要求的(您可以很好地处理您的元组)-它只会让事情变得更容易。
然后按如下方式运行查询:
db.run(
(
suppliers
join coffees on (_.id === _.supID)
)
.result
.map { results: Seq[(Supplier, Coffee)] =>
results
.groupBy(_._1)
.map { case (supp, groupped) =>
SupplierComposite(
id = supp.id,
name = supp.name,
...
coffees = groupped.map(_._2)
)
}
}
)
无论都不可能实现这样的事情:
我还希望有允许以级联模式更新Supplier对象和内部Coffee对象的方法。
这些功能根本不属于Slick
试图实现的目标。虽然它绝对可以达到经典的ORM
类sHibernate或(来自Scala World)eBean。
请注意-此功能(如上所述)基本上是ORM
中固有问题的根源之一--即object relational impedance mismatch--也正是Slick
想要避免的东西。
这篇关于如何建立与SLICK的反向关系模型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!