Slick 3.0 - 更新表中的列并返回整个表对象? [英] Slick 3.0 - Update columns in a table and return whole table object?
本文介绍了Slick 3.0 - 更新表中的列并返回整个表对象?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
这是 Slick 2 的实现.
Here is the implementation for Slick 2.
有人知道如何在 Slick 3 中实现这一点吗?
Does anyone have ideas about how to implement this in Slick 3?
推荐答案
我能够通过扩展 Tim Harper 在 https://stackoverflow.com/a/28148606/310275
I was able to make this work by extending the awesome work by Tim Harper in https://stackoverflow.com/a/28148606/310275
这是我现在所做的:
package utils
import scala.language.existentials
import slick.ast._
import slick.driver.PostgresDriver._
import slick.driver.PostgresDriver.api._
import slick.jdbc.{GetResult, JdbcResultConverterDomain, SetParameter, StaticQuery ⇒ Q, StaticQueryInvoker, StreamingInvokerAction}
import slick.profile.SqlStreamingAction
import slick.relational.{CompiledMapping, ResultConverter}
import slick.util.SQLBuilder
object Slick {
object UpdateReturning {
implicit class UpdateReturningInvoker[E, U, C[_]](updateQuery: Query[E, U, C]) {
def updateReturning[A, F](returningQuery: Query[A, F, C], v: U)(implicit db: Database) = {
val ResultSetMapping(_,
CompiledStatement(_, sres: SQLBuilder.Result, _),
CompiledMapping(_updateConverter, _)) = updateCompiler.run(updateQuery.toNode).tree
val returningNode = returningQuery.toNode
val fieldNames = returningNode match {
case Bind(_, _, Pure(Select(_, col), _)) =>
List(col.name)
case Bind(_, _, Pure(ProductNode(children), _)) =>
children.map { case Select(_, col) => col.name }.toList
case Bind(_, TableExpansion(_, _, TypeMapping(ProductNode(children), _, _)), Pure(Ref(_), _)) =>
children.map { case Select(_, col) => col.name }.toList
}
implicit val pconv: SetParameter[U] = {
val ResultSetMapping(_, compiled, CompiledMapping(_converter, _)) = updateCompiler.run(updateQuery.toNode).tree
val converter = _converter.asInstanceOf[ResultConverter[JdbcResultConverterDomain, U]]
SetParameter[U] { (value, params) =>
converter.set(value, params.ps)
}
}
implicit val rconv: GetResult[F] = {
val ResultSetMapping(_, compiled, CompiledMapping(_converter, _)) = queryCompiler.run(returningNode).tree
val converter = _converter.asInstanceOf[ResultConverter[JdbcResultConverterDomain, F]]
GetResult[F] { p => converter.read(p.rs) }
}
val fieldsExp = fieldNames.map(quoteIdentifier).mkString(", ")
val pconvUnit = pconv.applied(v)
val sql = sres.sql + s" RETURNING ${fieldsExp}"
val unboundQuery = Q.query[U, F](sql)
val boundQuery = unboundQuery(v)
new StreamingInvokerAction[Vector[F], F, Effect] {
def statements = List(boundQuery.getStatement)
protected[this] def createInvoker(statements: Iterable[String]) = new StaticQueryInvoker[Unit, F](statements.head, pconvUnit, (), rconv)
protected[this] def createBuilder = Vector.newBuilder[F]
}.asInstanceOf[SqlStreamingAction[Vector[F], F, Effect]]
}
}
}
}
它需要他的代码然后将 StaticQuery
转换为 SqlStreamingAction
It takes his code then transforms the StaticQuery
into a SqlStreamingAction
import utils.Slick.UpdateReturning._
val update = Users.filter(_.id === 1).map(_.firstName).
updateReturning(Users.map(_.firstName), ("Jane"))
val firstName = db.run(update.headOption).futureValue.get
firstName must === ("Jane")
这篇关于Slick 3.0 - 更新表中的列并返回整个表对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
查看全文