【问题标题】:Slick 3.0 how to update variable column list, which number is know only in RuntimeSlick 3.0如何更新变量列列表,只有在运行时才知道哪个数字
【发布时间】:2015-09-08 18:05:53
【问题描述】:

slick 3.0 是否可以更新变量列列表,只有在运行时才知道哪个数字?

下面是我想做的例子(不会编译)

var q: Query[UserTable, UserTable#TableElementType, Seq] = userTable
var columns = List[Any]()
var values = List[Any]()

if (updateCommands.name.isDefined) {
  columns = q.name :: columns
  values = updateCommands.name.get :: values
}

if (updateCommands.surname.isDefined) {
  columns = q.surname :: columns
  values = updateCommands.surname.get :: values
}
q = q.filter(_.id === updateCommands.id).map(columns).update(values)

【问题讨论】:

    标签: scala slick-3.0


    【解决方案1】:

    这是我在 Slick 3.1 中所做的。我不确定更糟糕的是,编辑普通的 SQL 语句或多个查询。所以我决定使用后者,假设 Postgres 优化器会在单个事务的更新查询中看到相同的 WHERE 子句。我的更新方法是这样的

    def updateUser(user: User, obj: UserUpdate): Future[Unit] = {
    
      val actions = mutable.ArrayBuffer[DBIOAction[Int, NoStream, Write with Transactional]]()
      val query = users.withFilter(_.id === user.id)
    
      obj.name.foreach(v => actions += query.map(_.name).update(v))
      obj.email.foreach(v => actions += query.map(_.email).update(Option(v)))
      obj.password.foreach(v => actions += query.map(_.pwdHash).update(Option(encryptPassword(v))))
    
      slickDb.run(DBIO.seq(actions.map(_.transactionally): _*))
    }
    

    【讨论】:

    • 我认为最后一行将使每个操作都使用自己的事务。要为整个操作序列拥有相同的事务,我们应该使用:slickDb.run(DBIO.seq(actions: _*).transactionally)
    • 如何查看交易结果?只需运行一次更新,您就可以得到修改的行数。
    【解决方案2】:

    在 Slick 3.0 中,他们采用了稍微不同的方法,而不是 updateAll 方法,就我而言,采用了组合器的用户立场路径。

    所以主要思想是在数据上定义一些操作,然后将它们组合到数据库上以进行单次运行。 示例:

    // let's assume that you have some table classes defined somewhere
    
    // then let's define some actions, they might be really different
    val action: SqlAction = YourTable.filter(_id === idToAssert)
    val anotherAction = AnotherTable.filter(_.pets === "fun")
    
    // and then we can combine them on a db.run 
    val combinedAction =  for {
      someResult <- action
      anotherResult <- anotherAction
    } yeild (someResult,anotherResult)
    
    db.run(combinedAction) // that returns actual Future of the result type
    

    您可以用同样的方式处理列表和序列,请看这里:http://slick.typesafe.com/doc/3.1.0-M1/dbio.html DBIO 具有一些功能,可让您将操作列表组合为一个操作。

    我希望这个想法很清楚,如果您有任何问题,欢迎来到 cmets。

    【讨论】:

      【解决方案3】:

      要更新可变数量的列,您可以使用我用于 slick 3 的这种方式:

        def update(id: Long, schedule: Schedule, fieldNames: Seq[String]): Future[_] = {
      val columns = schedules.baseTableRow.create_*.map(_.name).toSeq.filter(fieldNames.map(_.toUpperCase).contains)
      val toBeStored = schedule.withDefaults
      
      val actions = mutable.ArrayBuffer[DBIOAction[Int, NoStream, Write with Transactional]]()
      val query = schedules.withFilter(_.id === id)
      
      //this is becasue of limitations in slick, multiple columns are not possible to be updated!
      
      columns.find("NAME".equalsIgnoreCase).foreach(x => actions += query.map(_.name).update(toBeStored.name))
      columns.find("NAMESPACE".equalsIgnoreCase).foreach(x => actions += query.map(_.namespace).update(toBeStored.namespace))
      columns.find("URL".equalsIgnoreCase).foreach(x => actions += 
      
      db.run(DBIO.seq(actions: _ *).transactionally.withPinnedSession)
      

      }

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-04-12
        • 2011-08-18
        • 2015-07-24
        • 2018-05-31
        • 1970-01-01
        • 1970-01-01
        • 2022-12-18
        • 2016-03-05
        相关资源
        最近更新 更多