2016-05-20 2 views
0

мне нужно использовать Slick 3.1.1 для проекта на основе Postgres, но у меня есть трудное время, чтобы написать чистый код для следующего супер простого использования:Какова наилучшая практика простого Slick INSERT/GET?

Предположим у меня есть Task модель:

case class Task(id: Option[UUID], foo: Int, bar: String) 

id: UUID является основным ключом, поэтому я НЕ должен его предоставлять (id = None) при выполнении базы данных INSERT. Однако мне это нужно, когда вы делаете GET, который сопоставляет строку базы данных с объектом Task.

Поэтому Slick класс таблица становится очень некрасиво:

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

Если случай класс Task имеет 10 элементов, я тогда должен написать (tuple._1, tuple._2, tuple._3, ......) Мои сотрудники хлопнет мое лицо, если я представить PR как выше , Пожалуйста, предложите!

+0

Вы можете определить, что на уровне базы данных. Проверьте документы на странице http://slick.lightbend.com/doc/3.0.0/queries.html#inserting. «Когда вы включаете столбец AutoInc в операции вставки, он молча игнорируется, так что база данных может генерировать правильное значение». Это означает, что вы можете передать фиктивное значение, а db будет автоматически увеличивать id – pedrorijo91

+0

. Я заметил это в документе. Но я считаю, что это может сделать код менее простым. – SexyNerd

ответ

0

Если вы позволите базу данных для Autoincrement ваших идентификаторов, что определения таблицы может быть значительно сокращено:

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") 
+0

У меня возникла ошибка компиляции: '' '[error] found: ((Int, String)) => models.Task [error] required: ((Int, String, Option [UUID])) =>? [error]) .shaped. <> (Task.tupled, Task.unapply) [error]^ '' ' – SexyNerd

+0

Похоже, вы не используете' id' в своем 'def *' методе. Не могли бы вы разместить здесь свой код? –