我试图在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对象。
答案 0 :(得分:6)
答案很简单:你不能。 Slick
是FRM
(函数关系映射)并简单地说 - 它将关系元组映射到Scala对象(通常是tuples
/ case classes
)。您想要实现的内容在标准SQL中不易表达,因此无法直接在Slick
中表达。我在这里特别提到标准SQL - 因为我知道有些数据库允许您将某些字段分组并聚合到列表或数组中 - 但这远远超出了标准SQL范围,老实说我甚至都不是确保你能够在一般情况下这样做。
您可以在某种程度上模仿查询,在SELECT
之间使用JOIN
在两个表之间进行分组,然后对结果进行分组(这里重要的是 - 结果,我不是在谈论SQL { {1}} )获取GROUP BY
列表。
这可能是这样的:
首先 - 将您的表定义映射到案例类 - 所以代替:
coffees
这样做:
class Coffees(tag: Tag) extends Table[(String, Int, Double, Int, Int)]
并且可能将现有的class Coffees(tag: Tag) extends Table[Coffee]
案例类重命名为Supplier
或其他任何意味着它没有严格映射到db表但又是两个不同表的组合。
与SupplierComposite
相同。
它并不是严格要求的(你的元组会很好) - 它只会让事情变得更容易。
然后你会像这样运行你的查询:
Supplier
无法无论如何实现这样的目标:
此外,我想有一些方法允许以级联模式更新Supplier对象和Coffee对象。
这些功能根本不属于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)
)
}
}
)
试图实现的功能。绝对是经典的Slick
s的触手可及 - 如Hibernate或(来自Scala世界)eBean。
ORM
中固有的问题根源的起点之一 - 即object relational impedance mismatch - 正是这个问题ORM
希望避免。