使用 scala slick 重写此 SQL 查询
Rewrite this SQL query using scala slick
class ItemTable(tag: Tag) extends Table[Item](tag, _tableName = "items") {
def id: Rep[Int] = column[Int]("id", O.PrimaryKey, O.AutoInc)
def authId: Rep[String] = column[String]("auth_id")
def productId: Rep[Int] = column[Int]("product_id")
def position: Rep[Int] = column[Int]("position")
override def * : ProvenShape[Item] = (id, authId, productId, position) <> ((Item.apply _).tupled, Item.unapply)
}
class ItemService @Inject()(protected val dbConfigProvider: DatabaseConfigProvider)(implicit executionContext: ExecutionContext) {
private lazy val query = TableQuery[ItemTable]
def updateItem(item: Item, previousPosition: Int): Future[Item] = {
if (previousPosition < item.position) {
// this is the sql I want to convert to slick
db.run(sqlu""" UPDATE #${query.baseTableRow.tableName} SET position = position - 1 WHERE position >= #$previousPosition AND position <= #${item.position} AND auth_id = '#${item.authId}'""")
}
else if (previousPosition > item.position) {
db.run(sqlu""" UPDATE #${query.baseTableRow.tableName} SET position = position + 1 WHERE position <= #$previousPosition AND position >= #${item.position} AND auth_id = '#${item.authId}' """)
}
else {
// some other code
}
}
}
case class Item(id: Int, authId: String, productId: Int, position: Int){}
我的 SQL 有效,我被困在这里将它翻译成 slick。
val q2 = query.filter(f=> f.authId === item.authId && f.position >= previousPosition && f.position <= item.position)
//不知道如何更新多个或者把结果集传给更新函数
Slick 的嵌入式样式不支持 SET position = position + 1
(Slick issue 497).
形式的动态变异批量更新
这意味着使用您已有的普通 SQL 样式是正确的方法。
关于惯用语 sqlu
的附加说明:我注意到 sqlu
您使用了 "splicing"(#$
作为table 姓名)。这会阻止 Slick 将该值视为适合您正在执行的操作的字符串。但后来的用法 #$previousPosition
更通常写成普通替换 $previousPosition
。那是因为您通常希望 Slick 正确转义那里的 SQL 参数。它可能不会对整数产生影响,但对其他数据类型可能会产生影响。
class ItemTable(tag: Tag) extends Table[Item](tag, _tableName = "items") {
def id: Rep[Int] = column[Int]("id", O.PrimaryKey, O.AutoInc)
def authId: Rep[String] = column[String]("auth_id")
def productId: Rep[Int] = column[Int]("product_id")
def position: Rep[Int] = column[Int]("position")
override def * : ProvenShape[Item] = (id, authId, productId, position) <> ((Item.apply _).tupled, Item.unapply)
}
class ItemService @Inject()(protected val dbConfigProvider: DatabaseConfigProvider)(implicit executionContext: ExecutionContext) {
private lazy val query = TableQuery[ItemTable]
def updateItem(item: Item, previousPosition: Int): Future[Item] = {
if (previousPosition < item.position) {
// this is the sql I want to convert to slick
db.run(sqlu""" UPDATE #${query.baseTableRow.tableName} SET position = position - 1 WHERE position >= #$previousPosition AND position <= #${item.position} AND auth_id = '#${item.authId}'""")
}
else if (previousPosition > item.position) {
db.run(sqlu""" UPDATE #${query.baseTableRow.tableName} SET position = position + 1 WHERE position <= #$previousPosition AND position >= #${item.position} AND auth_id = '#${item.authId}' """)
}
else {
// some other code
}
}
}
case class Item(id: Int, authId: String, productId: Int, position: Int){}
我的 SQL 有效,我被困在这里将它翻译成 slick。
val q2 = query.filter(f=> f.authId === item.authId && f.position >= previousPosition && f.position <= item.position)
//不知道如何更新多个或者把结果集传给更新函数
Slick 的嵌入式样式不支持 SET position = position + 1
(Slick issue 497).
这意味着使用您已有的普通 SQL 样式是正确的方法。
关于惯用语 sqlu
的附加说明:我注意到 sqlu
您使用了 "splicing"(#$
作为table 姓名)。这会阻止 Slick 将该值视为适合您正在执行的操作的字符串。但后来的用法 #$previousPosition
更通常写成普通替换 $previousPosition
。那是因为您通常希望 Slick 正确转义那里的 SQL 参数。它可能不会对整数产生影响,但对其他数据类型可能会产生影响。