Как изменить тип отмененных типов до типов Scala при использовании вложенных вложений Slick?

Как вы "поднимите" значение внутри запроса в Slick при использовании поднятого вложения? Я надеялся, что "получить", "toLong" или что-то вроде этого может сделать трюк, но такой удачи нет.

Следующий код не компилируется:

  val userById = for {
     uid <- Parameters[Long]
     u <- Users if u.id === uid
  } yield u

  val userFirstNameById = for {
     uid <- Parameters[Long]
     u <- userById(uid)
     ---------------^
     // type mismatch;  found   : scala.slick.lifted.Column[Long]  required: Long
  } yield u.name

Ответ 1

Вы не можете по двум причинам:

1) с val это происходит во время компиляции, нет Longзначение uid. userById(uid) связывает a Long uid со временем компиляции сгенерированный подготовленный оператор, а затем .list, .first и т.д. invoke запрос.

2) другая проблема возникает, как только вы Parameter выберите запрос, композиция уже невозможна - это ограничение, относящееся к ScalaQuery.

Лучше всего отложить Parameter до окончательного скомпонованного запроса:

val forFooBars = for{
  f <- Foos
  b <- Bars if f.id is b.fooID
} yield(f,b)
val allByStatus = for{ id ~ active <- Parameters[(Long,Boolean)]
  (f,b) <- forFooBars if (f.id is id) && (b.active is active)
} yield(f,b)

def findAllByActive(id: Long, isActive: Boolean) = allByStatus(id, isActive).list

Во всяком случае, в вашем примере вы могли бы так же хорошо:

val byID = Users.createFinderBy(_.id)

Единственный способ, с помощью которого я могу работать, это обернуть запрос val в def и передать переменную среды выполнения, что означает, что Slick должен повторно генерировать sql для каждого запроса, и никакой подготовленный оператор не отправляется в базовую СУБД. В некоторых случаях вам нужно сделать это, например, передать List(1,2,3) для inList.

def whenNothingElseWorks(id: Long) = {
  val userFirstNameById = for {u <- userById(id.bind)} yield u.name
}