Slick 3.0 how to update variable column list, which number is know only in Runtime

て烟熏妆下的殇ゞ 提交于 2019-12-07 02:32:14

问题


Is it possible to update variable column list, which number is know only in runtime by slick 3.0?

Below is example what I want to do (won't compile)

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)

回答1:


Here is what I've done in Slick 3.1. I wasn't sure what worse, editing plain SQL statement or multiple queries. So I decided to go with latter assuming Postgres optimizer would see same WHERE clause in update queries of single transaction. My update method looks like this

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): _*))
}



回答2:


In Slick 3.0 they adopted slightly different approach, instead of having updateAll methods, as far as I userstand path of combinators was adopted.

So main idea is to define some actions on the data and then combine them ont he database to make a single run. Example:

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

In the same way you can deal with lists and sequences, for that please take a look here: http://slick.typesafe.com/doc/3.1.0-M1/dbio.html DBIO has some functions that allows you to combine list of actions to one action.

I hope that idea is clear, if you have questions you are wellcome to the comments.




回答3:


to update a variable number of columns you may use this way as I used for 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)

}



来源:https://stackoverflow.com/questions/32464435/slick-3-0-how-to-update-variable-column-list-which-number-is-know-only-in-runti

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!