Slick-使用foreignKey约束并直接作为列访问引用的对象 [英] Slick- use foreignKey constraint and access referenced object directly as column



我有两个模型(例如,SupplierCoffee),Coffee 模型具有对供应商模型的外键引用.在 ddl 期间,我希望这种关系存在于表创建中.但我也希望能够通过像 这样的 Coffee 对象来引用 Supplier 对象.下面是我的虚拟代码.我正在使用 MappedTable, foreignKeyTypeMapper.

I have two models (say, Supplier and Coffee) and Coffee model has foreign key reference to Supplier model. During ddl, I want this relationship to exist in table creation. But I also want to be able to refer the Supplier object through Coffee object like Below is my dummy code. I am using MappedTable, foreignKey and TypeMapper.

import scala.slick.driver.H2Driver.simple._
import Database.threadLocalSession

object SlickTest {
  // Supplier
  case class Supplier(id: Option[Int], name: String)
  object Suppliers extends Table[Supplier]("supplier") {
    def id = column[Int]("id", O.PrimaryKey, O.AutoInc)
    def name = column[String]("name")
    def * = id.? ~ name <> (Supplier, Supplier.unapply _)
    def findOneById(id: Int): Supplier = { e => e }.where(r => === id).firstOption.get

  // Implicit Conversion from Supplier to Int
  implicit val supTypeMapper = MappedTypeMapper.base[Supplier, Int](
    { s => }, { id => Suppliers.findOneById(id) })

  // Coffee
  case class Coffee(name: Option[String], sup: Supplier, price: Double)
  object Coffees extends Table[Coffee]("coffee") {
    def name = column[String]("cof_name", O.PrimaryKey)
    def sup = column[Supplier]("supplier")
    def price = column[Double]("price")
    def * = name.? ~ sup ~ price <> (Coffee, Coffee.unapply _)

    def supplier = foreignKey("SUP_FK", sup, Suppliers)(

代码在supplier 定义的最后一行失败.有人能解释一下吗?

The code is failing at the last line for the definition of supplier. Could anyone shed any light?


在 Slick 中,您不会映射到引用其他案例类的案例类.要解析外键,您可以改用查询,您可以将其放入可重用的方法中.

In Slick you don't map to case classes that reference other case classes. To resolve foreign keys you use queries instead, which you can put into methods for re-usability.


您不能遵循 coffeeObj 中的参考,这是一件好事.因为这需要像在 ORM 中那样配置加载策略,这会更加复杂,并且会使代码的执行行为不那么明显.

You can't follow a reference in coffeeObj and that is a good thing. Because that would require configuring a loading strategy like in ORMs, which would be more complicated and would make the execution behavior of your code less obvious.


Lazy loading would probably load the coffeeObj in the controller and the supplier in the view, which seems odd, right? You can do this:

Remove .firstOption.get 从您的 findOneById 方法中,然后:

Remove .firstOption.get from your findOneById method and then:

val supplierQuery = Query(Suppliers).findById(id)
val coffeeQuery = supplierQuery.join(Coffee).on(...).map(_._2)
// here is what you want, a supplier and the corresponding coffee:
val supplierWithCoffee = (supplierQuery.firstOption,coffeeQuery.f​irstOption)


Put the join into a function to save boiler plate.


登录 关闭
发送“验证码”获取 | 15天全站免登陆