简单的Slick INSERT / GET的最佳实践是什么?

时间:2016-05-20 06:28:22

标签: postgresql scala slick-3.0

我需要将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, ......)如果我提交上面的公关,我的同事会拍我的脸。请提出建议!

1 个答案:

答案 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")