Tính năng này không được hỗ trợ trong Slick (v2 hoặc v3-M1); mặc dù tôi không thấy bất kỳ lý do cụ thể nào cấm triển khai, UPDATE ... RETURNING
không phải là tính năng SQL chuẩn (ví dụ: H2 không hỗ trợ tính năng này: http://www.h2database.com/html/grammar.html#update). Tôi sẽ để lại như là một bài tập cho người đọc để khám phá làm thế nào một cách an toàn và hiệu quả mô phỏng tính năng cho RDBMSes thiếu UDPATE ... RETURNING
.
Khi bạn gọi "trả lại" trên số scala.slick.lifted.Query
, số này cung cấp cho bạn JdbcInsertInvokerComponent$ReturningInsertInvokerDef. Bạn sẽ không tìm thấy phương thức update
, mặc dù có phương thức insertOrUpdate
; tuy nhiên, insertOrUpdate
chỉ trả lại kết quả biểu hiện returning
nếu chèn xảy ra, None
được trả về để cập nhật, do đó, không có trợ giúp ở đây.
Từ điều này, chúng tôi có thể kết luận rằng nếu bạn muốn sử dụng tính năng SQL UPDATE ... RETURNING
, bạn sẽ cần phải sử dụng StaticQuery hoặc cuộn bản vá của riêng bạn vào Slick. Bạn có thể tự tay viết các truy vấn của bạn (và tái thực hiện dự bảng của bạn như getResult/setParameter serializers), hoặc bạn có thể thử đoạn mã này:
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
}
}
}
Tôi chắc chắn ở trên có thể được cải thiện; Tôi đã viết nó dựa trên sự hiểu biết hơi hạn chế của tôi về nội dung Slick, và nó làm việc cho tôi và có thể tận dụng các dự báo/loại ánh xạ mà bạn đã xác định.
Cách sử dụng:
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")))
Tôi không hiểu liệu bạn muốn cập nhật một đối tượng và gửi lại hoặc bạn muốn cập nhật một đối tượng và sau đó có 'TableQuery' với bản cập nhật bạn chỉ cần làm, nếu thứ hai có lẽ bạn chỉ phải nối '.run' vào truy vấn bạn đang thực hiện. –
Giả sử rằng tôi có một phép chiếu đầy đủ từ một 'trường hợp lớp' đến các cột của bảng, tôi muốn cập nhật một tập con của các cột đó (tức là' .map (x => (x.someColumn, x.anotherColumn)) Vì vậy, trong ví dụ trên, SomeTables có thể có một phép chiếu '*' mặc định sẽ có 5 colums, tôi đang cập nhật hai cột ('someColumn' và' anotherColumn' khác.), tuy nhiên tôi muốn trả lại toàn bộ 'bảng' (hoặc đối tượng) có chứa 5 cột – mdedetrich
Từ trải nghiệm mới bắt đầu của tôi, tôi không thấy cách nào ngoại trừ cập nhật và sau đó chọn hàng, phương thức' cập nhật' bạn ' gọi lại trả về một 'Int' (đó là liệu việc cập nhật thành công hay không) Xin lỗi tôi không thể giúp, hy vọng ai đó có nhiều kinh nghiệm hơn sẽ trả lời –