如何使用Slick的映射表与外键? [英] How to use Slick's mapped tables with foreign keys?

查看:326
本文介绍了如何使用Slick的映射表与外键?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在努力与Slick的解除嵌入和映射表。 API对我来说很奇怪,也许只是因为它的结构对我不熟悉。



我想建立一个Task / Todo-List。有两个实体:




  • 任务:每个任务都有一个对下一个任务的可选引用。这样就构建了一个链表。意图是用户可以通过他的优先级来订购任务。这个顺序是由任务到任务的引用表示的。

  • TaskList:表示一个带有标签和对列表第一个任务的引用的TaskList。



    案例类任务(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

隐式val会话:Session = Database.threadLocalSession
val queryById = Tasks.createFinderBy(t => t.id)

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

private object任务扩展表[任务](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.unapply _)
}

私有对象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 _)
}

问题出现在 $ c>。




  • 无法找到类型
    的evidence参数的隐式值scala.slick.lifted.TypeMapper [ scala.slick.lifted.ForeignKeyQuery [SlickTaskRepository.this.Tasks.type,justf0rfun.bookmark.model.Task]]

  • 可以找不到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)=& id
case _ =>无
})




  • 找不到参数tm的隐含值:scala.slick.lifted.TypeMapper [Option [justf0rfun.bookmark.model.Task]]

  • 方法base:的参数不够(implicit tm:scala.slick.lifted.TypeMapper [Option [justf0rfun.bookmark.model.Task]])scala.slick.lifted.BaseTypeMapper [选项[长]]。未指定的值参数tm。



主要问题:如何使用Slick提升的嵌入和映射表正确的方式?



提前感谢。

解决方案

简短的回答是:使用ids而不是对象引用,并使用Slick查询来解除引用id。



这将使你的case类看起来像这样:

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



我会在某个时候发布关于这个主题的文章并链接到这里。 p>

I'm struggling with Slick's lifted embedding and mapped tables. The API feels strange to me, maybe just because it is structured in a way that's unfamiliar to me.

I want to build a Task/Todo-List. There are two entities:

  • Task: Each task has a an optional reference to the next task. That way a linked list is build. The intention is that the user can order the tasks by his priority. This order is represented by the references from task to task.
  • TaskList: Represents a TaskList with a label and a reference to the first Task of the list.

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


Now I tried to write a data access object (DAO) for these two entities.

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 _)
  }

Unfortunately it does not compile. The problems are in the * projection of both tables at nextTask respective firstTask.

  • 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]]

I tried to solve that with the following TypeMapper but that does not compile, too.

  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.

Main question: How to use Slick's lifted embedding and mapped tables the right way? How to I get this to work?

Thanks in advance.

解决方案

The short answer is: Use ids instead of object references and use Slick queries to dereference ids. You can put the queries into methods for re-use.

That would make your case classes look like this:

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

I'll publish an article about this topic at some point and link it here.

这篇关于如何使用Slick的映射表与外键?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆