【问题标题】:How to use Slick's mapped tables with foreign keys?如何使用带有外键的 Slick 映射表?
【发布时间】:2013-07-24 09:47:44
【问题描述】:

我正在为 Slick 提升的嵌入和映射表而苦苦挣扎。 API 对我来说感觉很奇怪,也许只是因为它的结构对我来说是不熟悉的。

我想建立一个任务/待办事项列表。有两个实体:

  • 任务:每个任务都有一个对下一个任务的可选引用。这样就建立了一个链表。目的是用户可以按他的优先级对任务进行排序。此顺序由任务到任务的引用表示。
  • TaskList:表示一个TaskList,带有一个标签和对列表第一个Task的引用。

    case class Task(id: Option[Long], title: String, nextTask: Option[Task])
    case class TaskList(label: String, firstTask: Option[Task])


现在我尝试为这两个实体编写一个数据访问对象 (DAO)。

import scala.slick.driver.H2Driver.simple._
import slick.lifted.MappedTypeMapper

implicit val session: Session = Database.threadLocalSession
val queryById = Tasks.createFinderBy( t => t.id )

def task(id: Long): Option[Task] = queryById(id).firstOption

  private object Tasks extends Table[Task]("TASKS") {
    def id = column[Long]("ID", O.PrimaryKey, O.AutoInc)
    def title = column[String]("TITLE")
    def nextTaskId = column[Option[Long]]("NEXT_TASK_ID")
    def nextTask = foreignKey("NEXT_TASK_FK", nextTaskId, Tasks)(_.id)
    def * = id ~ title ~ nextTask <> (Task, Task.unapply _)
  }

  private object TaskLists extends Table[TaskList]("TASKLISTS") {
    def label = column[String]("LABEL", O.PrimaryKey)
    def firstTaskId = column[Option[Long]]("FIRST_TASK_ID")
    def firstTask = foreignKey("FIRST_TASK_FK", firstTaskId, Tasks)(_.id)
    def * = label ~ firstTask <> (Task, Task.unapply _)
  }

不幸的是它没有编译。问题出在nextTaskfirstTask 的两个表的* 投影中。

  • could not find implicit value for evidence parameter of type scala.slick.lifted.TypeMapper[scala.slick.lifted.ForeignKeyQuery[SlickTaskRepository.this.Tasks.type,justf0rfun.bookmark.model.Task]]
  • could not find implicit value for evidence parameter of type scala.slick.lifted.TypeMapper[scala.slick.lifted.ForeignKeyQuery[SlickTaskRepository.this.Tasks.type,justf0rfun.bookmark.model.Task]]

我尝试使用以下 TypeMapper 解决该问题,但也无法编译。

  implicit val taskMapper = MappedTypeMapper.base[Option[Long], Option[Task]](
    option => option match {
      case Some(id) => task(id)
      case _ => None
    },
    option => option match {
      case Some(task) => task.id
      case _ => None
    })
  • could not find implicit value for parameter tm: scala.slick.lifted.TypeMapper[Option[justf0rfun.bookmark.model.Task]]
  • not enough arguments for method base: (implicit tm: scala.slick.lifted.TypeMapper[Option[justf0rfun.bookmark.model.Task]])scala.slick.lifted.BaseTypeMapper[Option[Long]]. Unspecified value parameter tm.

主要问题:如何正确使用 Slick 的提升嵌入和映射表?如何让它工作?

提前致谢。

【问题讨论】:

    标签: database scala orm persistence slick


    【解决方案1】:

    简短的回答是:使用 id 代替对象引用,并使用 Slick 查询取消引用 id。您可以将查询放入方法中以供重复使用。

    这将使您的案例类看起来像这样:

    case class Task(id: Option[Long], title: String, nextTaskId: Option[Long])
    case class TaskList(label: String, firstTaskId: Option[Long])
    

    我会在某个时候发表一篇关于这个主题的文章并在此处链接。

    【讨论】:

    • 嗨 cvogt,这个限制对于 Slick 2.0 是否仍然存在?你有关于这种情况应该如何排序的参考吗?谢谢!
    • 嗨。您发表文章了吗?
    • 不,但它仍在我的清单上,并且可能会在夏天之前的某个时间发生。我会在 Slick 邮件列表上公布。
    • 文章发表了吗?
    猜你喜欢
    • 2014-12-31
    • 1970-01-01
    • 2012-11-23
    • 1970-01-01
    • 1970-01-01
    • 2023-03-08
    • 2020-11-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多