我需要将Slick 3.1.1用于基于Postgres的项目,但我很难为以下超级简单的用法编写干净的代码:
假设我有一个Task
模型:
case class Task(id: Option[UUID], foo: Int, bar: String)
id: UUID
是主键,所以在进行数据库INSERT时我不应该提供它(id = None
)。但是,在执行将数据库行映射到Task对象的GET时,我确实需要它。
因此,Slick Table类变得非常难看:
class Tasks(tag: Tag) extends Table[Task](tag, "tasks") {
def id = column[UUID]("id", O.SqlType("UUID"), O.PrimaryKey)
def foo = column[Int]("foo")
def bar = column[String]("bar")
def insert: MappedProjection[Task, (Int, String)] =
(foo, bar).shaped.<>(
{ tuple =>
Task.tupled(None, tuple._1, tuple._2)
}, { (task: Task) =>
Task.unapply(task).map { tuple =>
(tuple._2, tuple._3)
}
}
)
override def * : ProvenShape[Task] =
(id.?,
foo,
bar).shaped.<>(Task.tupled, Task.unapply)
}
如果案例类任务有10个元素,那么我必须写(tuple._1, tuple._2, tuple._3, ......)
如果我提交上面的公关,我的同事会拍我的脸。请提出建议!
答案 0 :(得分:0)
如果您让数据库自动增加您的ID,那么表定义可能会显着缩短:
import slick.driver.PostgresDriver.api._
import java.util.UUID
case class Task(id: Option[UUID], foo: Int, bar: String)
class Tasks(tag: Tag) extends Table[Task](tag, "tasks") {
def id = column[Option[UUID]]("id", O.SqlType("UUID"), O.PrimaryKey, O.AutoInc)
def foo = column[Int]("foo")
def bar = column[String]("bar")
def * = (id, foo, bar) <> (Task.tupled, Task.unapply)
}
通过将id
字段移动到案例类的末尾并为其提供默认的None
值,可以进一步改进这一点。这样,每次要实例化Task
时,您都不必提供它:
case class Task(foo: Int, bar: String, id: Option[UUID] = None)
val firstTask = Task(123, "John")
val secondTask = Task(456, "Paul")