当前位置: 首页 > 面试题库 >

Slick 2-更新表中的列并返回整个表对象

家浩瀚
2023-03-14
问题内容

当使用平滑功能时,如何在返回一个更新的表的同时更新一个表中的几列?

假设SomeTables有一些TableQuery,例如,如果您想向表中添加一个项目(并返回新添加的项目),通常会编写这样的查询

val returnedItem = SomeTables returning SomeTables += someTable

如果您要更新商品并将整个商品退回整个商品,该怎么做,我怀疑您会做这样的事情

val q = SomeTables.filter(_.id === id).map(x => (x.someColumn,x.anotherColumn)) returning SomeTables
val returnedItem = q.update((3,"test"))

但是,以下代码不起作用,并且我看不到任何有关如何执行此操作的文档

请注意,我知道您可以事先查询该项目,对其进行更新,然后在原始对象上使用复制,但是这需要大量的样板(以及DB行程)


问题答案:

Slick(v2或v3-M1)不支持此功能。尽管我看不到任何禁止它实现的特定原因,但这UPDATE … RETURNING不是标准的SQL功能)。我将作为练习供读者阅读,以探讨如何安全有效地模拟缺少RDBMS的功能UDPATE … RETURNING。

当您在上调用“ returning”时scala.slick.lifted.Query,它会为您提供JdbcInsertInvokerComponent $ ReturningInsertInvokerDef。update尽管有一种insertOrUpdate方法,但您找不到任何方法。但是,insertOrUpdate仅在returning发生插入时才返回表达式结果,None并且返回表达式以进行更新,因此这里没有帮助。

由此可以得出结论,如果要使用UPDATE … RETURNINGSQL功能,则需要使用StaticQuery或将自己的补丁滚动到Slick。您可以手动编写查询(并以GetResult / SetParameter序列化器的形式重新实现表投影),也可以尝试以下代码段:

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
    }
  }
}

我敢肯定,上述情况可以改善;我是基于对Slick内部原理的有限了解而编写的,它对我有用,并且可以利用您已经定义的投影/类型映射。

用法:

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")))


 类似资料:
  • 问题内容: 我有一个整数列表,我想生成一个包含所有连续整数列表的列表。 我有以下可行的方法,但似乎做起来很糟糕: 我已经看到其他问题,表明itertools.groupby是执行此操作的有效方法,但是我对该函数不熟悉,而且似乎在编写lambda函数来描述连续性方面遇到麻烦。 问题:是否有更好的方法(可能使用itertools.groupby?) 注意事项:full_list将具有1到59之间的整数

  • 我有这个: 有没有办法可以得到更新后的列表,而不是就地更新原始列表?

  • 我对Spring编程是新手。我正在用Reactor/Webflux项目测试反应式编程。 数据库注册通过POST工作得很好。 我的模型: 我的存储库 我的用户服务

  • 我在Python中进行多元线性回归,但由于某种原因,系数没有正确返回为列表。相反,将返回列表中的列表: 这将返回列表[]的列表中的值,而不是列表[]。知道为什么会这样吗?输出: 但这行得通: 输出:

  • 这个问题是jOOQ的扩展:在单个对象中返回带有join、groupby和count的列表,但现在返回的是三个对象,而不是两个。 主意 具体示例 如何从查询中获取结果?

  • 问题内容: 我需要根据从以下两个表中提取的数据创建一个新表: 第一表: 第二张表: 新表应包含一个“ Var”列和一个“Number”列,其中每个变量将包含一行带有cur_number的行,其余各行将包含第二个表的new_number列中的数字,其中。例如,在上面显示的示例中,对于A,将有一行,行数为10(其cur_number),另一行为“ 2”(因为2 <10,但是11>10)。 在我的示例中