Slick 中的自定义列(对象)类型

Custom column (Object) type in Slick

我似乎无法在任何地方找到如何在 Slick 中正确使用自定义列类型,我已经苦苦挣扎了一段时间。光滑 documentation 建议 MappedColumnType 但我发现它仅适用于简单的用例,如原始类型包装器(或者可能只是我不知道如何正确使用它)。

假设我的数据库中有工作table JobsTableDef class。在 table 中,我有 companyIdresponsibleUserId 列,它们是 CompanyUser 对象在各自 table 中的外键(CompaniesTableDef, UsersTableDef).

class JobsTableDef(tag: Tag) extends Table[Job] (tag, "jobs") {

  def id = column[Long]("id", O.AutoInc, O.PrimaryKey)
  def title = column[String]("title")
  def companyId = column[Long]("companyId")
  def responsibleUserId = column[Long]("responsibleUserId")

  def companyFK = foreignKey("COMPANY_ID_FK", companyId, companies)(i => i.id)
  def responsibleUserFK = foreignKey("RESPONSIBLE_USER_FK", responsibleUserId, users)(i => i.id)

  val companies = TableQuery[CompaniesTableDef]
  val users = TableQuery[UsersTableDef]

  override def * = (id, title, companyId, responsibleUserId) <> (Job.tupled, Job.unapply)
}

class CompaniesTableDef(tag: Tag) extends Table[Company] (tag, "companies") {

  def id = column[Long]("id", O.AutoInc, O.PrimaryKey)
  def name = column[String]("name")
  def about = column[String]("about")

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

class UsersTableDef(tag: Tag) extends Table[User] (tag, "users"){

  def id = column[Long]("id", O.AutoInc, O.PrimaryKey)
  def username = column[String]("username", O.Unique)

  override def * = (id, username) <> (User.tupled, User.unapply)
}

我想实现的是自动'deserialize' CompanyUser 由他们在Jobs table 中的ID 表示。例如:

class JobsTableDef(tag: Tag) extends Table[Job] (tag, "jobs") {

  def id = column[Long]("id", O.AutoInc, O.PrimaryKey)
  def title = column[String]("title")
  def company = column[Company]("companyId")
  def responsibleUser = column[User]("responsibleUserId")

  def companyFK = foreignKey("COMPANY_ID_FK", companyId, companies)(i => i.id.?)
  def responsibleUserFK = foreignKey("RESPONSIBLE_USER_FK", responsibleUserId, users)(i => i.id.?)

  val companies = TableQuery[CompaniesTableDef]
  val users = TableQuery[UsersTableDef]

  override def * = (id, title, company, responsibleUser) <> (Job.tupled, Job.unapply)
}

鉴于我的 Job class 是这样定义的:

case class Job(
    id: Long,
    title: String,
    company: Company,
    responsibleUser: User,
)

目前,我正在以老式的方式从数据库中获取 Job,读取 companyIdresponsibleUserId,然后再次查询数据库并手动构建另一个Job对象(当然我也可以加入tables,获取数据为tuple,然后构造Job对象)。我严重怀疑这是要走的路。有没有一种更聪明、更优雅的方法来指示 Slick 自动从另一个 tables 中获取链接对象?

编辑:我正在使用 Play 2.6.12 和 Slick 3.2.2

经过几天的深入调查,我得出的结论是目前在 Slick 中这是不可能的。我正在寻找的可以描述为通过自定义列类型描述的自动连接表。 Slick 确实支持自定义列类型(通过 MappedColumnType 体现,如 docs 中所述),但它仅适用于相对简单的类型,这些类型不是由从 DB 反序列化的另一个对象组成的(至少自动地,你可以总是尝试从数据库中获取另一个对象,然后 Await.result() 结果 Future 对象,但我想这不是一个好的做法)。

所以,回答我自己,'auto joining' 在 Slick 中是不可能的,回到手动对象构建的手动连接。