Bu özellik Slick'te desteklenmiyor (v2 veya v3-M1); Ben herhangi bir özel nedeni UPDATE ... RETURNING
standart bir SQL özelliği değildir, gerçekleştirimdir yasaklayan görmüyorum rağmen (örneğin, H2 bunu desteklemez: http://www.h2database.com/html/grammar.html#update). Okuyucunun, birisinin UDPATE ... RETURNING
eksik olan RDBMS'ler için nasıl güvenli ve verimli bir şekilde öykünebileceğini araştırması için bir egzersiz olarak ayrılacağım.
scala.slick.lifted.Query
'da "dönen" i çağırdığınızda, size bir JdbcInsertInvokerComponent$ReturningInsertInvokerDef verir. insertOrUpdate
yöntemi olmasına rağmen update
yöntemini bulamazsınız; Ancak, insertOrUpdate
yalnızca bir ekleme gerçekleştiğinde returning
ifade sonucunu döndürür, güncelleştirmeler için None
döndürülür, bu nedenle burada yardım yok.
Bundan yola çıkarak, UPDATE ... RETURNING
SQL özelliğini kullanmak isterseniz, StaticQuery'u kullanmanız veya kendi yamağunuzu Slick'e döndürmeniz gerektiği sonucuna varabiliriz. Manuel sorguları yazma (ve GetResult/setParameter serileştiriciler olarak masa projeksiyonları yeniden uygulamak) veya bu kod parçacığını deneyebilirsiniz:
package com.spingo.slick
import scala.slick.driver.JdbcDriver.simple.{queryToUpdateInvoker, Query}
import scala.slick.driver.JdbcDriver.{updateCompiler, queryCompiler, quoteIdentifier}
import scala.slick.jdbc.{ResultConverter, CompiledMapping, JdbcBackend, JdbcResultConverterDomain, GetResult, SetParameter, StaticQuery => Q}
import scala.slick.util.SQLBuilder
import slick.ast._
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 session: JdbcBackend#Session): List[F] = {
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 sql = sres.sql + s" RETURNING ${fieldsExp}"
val unboundQuery = Q.query[U, F](sql)
unboundQuery(v).list
}
}
}
Yukarıda geliştirilebilir eminim; Ben biraz Slick internals benim sınırlı bir anlayış benim dayalı olarak yazdım ve benim için çalışır ve zaten tanımladığınız projeksiyonlar/tip-mappings kaldırabilir.
Kullanımı:
import com.spingo.slick.UpdateReturning._
val tq = TableQuery[MyTable]
val st = tq filter(_.id === 1048003) map { e => (e.id, e.costDescription) }
st.updateReturning(tq map (identity), (1048003, Some("such cost")))
Ben Bir nesneyi güncellemek ve bunu iade etmek isteyip anlamadığınız veya eğer, sadece yaptığımız güncelleme ile 'TableQuery' sahip sonra bir nesneyi güncellemek ve istediğiniz ikincisi muhtemelen yürütmekte olduğunuz sorguya '.run' eklemek zorundasınız. –
Bir "case class" öğesinden tablonun sütunlarına tam bir projeksiyon yaptığımı varsayarak, bu sütunların bir alt kümesini güncellemek istiyorum (örn. .map (x => (x.someColumn, x.anotherColumn)) , SomeTables varsayılan anotherColumn' '*' 5 colums olurdu projeksiyon, ben bu sütunların ikisini güncelleştiriyorum ('someColumn' ve' olabilir yukarıdaki örnek Yani 've. (' SomeTables' dönen) bütün güncellenen nesneyi döndürmek), ancak 5 sütun ben güncelleme haricinde bir çıkış yolu görmüyorum benim acemi deneyim – mdedetrich
içeren ve daha sonra 'update' yöntemi' satır, seçersiniz bütün' table' (veya nesneyi) dönmek istiyorum döner çağırarak yeniden bir 'Int' (bu güncellemenin başarılı olup olmadığıdır). umarım daha tecrübeli birisi cevap verecektir. –