Есть три места, где вы можете сделать это: на уровне Query
, на уровне DBIO
и (как вы отметили и отклонили) на уровне Future
.
Запрос
На уровне запроса преобразование будет происходить как часть выполнения запроса в собственном контексте выполнения Slick.
Это будет выглядеть примерно так:
// Given some query that returns a tuple...
val tupleQ: Query[(Rep[String],Rep[String]), (String,String), Seq] =
table.map{ row => (row.column1, row.column2) }
// ...which we'd like to project into this:
case class SomeCaseClass(v1: String, v2: String)
// ...we can use the mapTo macro to generate the conversion:
val ccQ: Query[Rep[SomeCaseClass], SomeCaseClass, Seq] =
tupleQ.map{ _.mapTo[SomeCaseClass] }
Еслиэто все, что вы делаете, тогда, может быть, для этого и используется проекция по умолчанию (def * ...
).
Если вам нужен больший контроль над логикой преобразования, вы можете использовать нижний уровень <>
вместо mapTo
. Раздел 5.2 Essential Slick дает более подробную информацию по этому вопросу.
DBIO
Вопрос был конкретно о DBIO
.Преобразование будет выполняться в вашем собственном контексте выполнения.
Это будет выглядеть примерно так:
// Given a DBIO that returns a tuple...
val tupleD: DBIO[Seq[(String,String)]] =
table.map(row => (row.column1, row.column2)).result
// ... we can use any of the DBIO combinators to convert it, such as map:
val ccD: DBIO[Seq[SomeCaseClass]] =
dQ.map{ pairs => pairs.map{ case (a, b) => SomeCaseClass(a,b) } }
(... или dQ.map(pairs => pairs.map(SomeCaseClass.tupled))
, как вы заметили).
Два больших преимущества, которые вы получите на этом уровне
- у вас есть доступ к значениям, таким как
(a,b)
, и вы можете принимать решения о том, что вы хотите делать со значениями. - являясь частью действияозначает, что вы можете принять участие в транскрипции.
Глава 4 Essential Slick перечисляет многие комбинаторы DBIO. Slick Manual также описывает комбинаторы.
Future
Финальное место занимает Future
, который очень похож на версию DBIO
, но послеdb.run
(как вы уже нашли).