修改列值后将 Slick 查询映射到默认投影
Mapping Slick query to default projection after modifying column value
创建 table 查询时,我想通过映射默认 table 查询来修改我的 select 语句。但是,我找不到一种方法来映射列的值并仍然映射到我的案例 class
case class MyRecord(id: Int, name: String, value: Int)
class MyTable(tag: Tag) extends Table[MyRecord](tag, "MYTABLE") {
def id = column[Int]("id")
def name = column[String]("name")
def value = column[Int]("value")
def * = (id, name, value) <> (MyRecord.tupled, MyRecord.unapply)
}
lazy val tableQuery = TableQuery[MyTable]
我想 trim name
的值与 :
def trimLeading0: (Rep[String]) => Rep[String] = SimpleExpression.unary[String, String] {
(str, queryBuilder) =>
import slick.util.MacroSupport._
import queryBuilder._
b"TRIM(LEADING 0 FROM $str)"
}
现在我不知道该做什么:
val trimmedTableQuery: Query[MyTable, MyRecord, Seq] = tableQuery.map(s => ???)
我试过映射 Rep
就像处理案例 class:
val trimmedTableQuery = tableQuery.map(s => s.copy(name = trimLeading0(s.name)))
这拒绝使用 value copy is not a member of MyTable
进行编译
我目前的解决方法是对默认投影使用自定义函数而不是 MyRecord.tupled
:
def trimming(t: (Int, String, Int)) = MyRecord(t._1, t._2.dropWhile(_ == "0"), t._3)
def * = (id, name, value) <> (trimming, MyRecord.unapply)
或者,我可以将返回元组的 DBIOAction
的返回结果映射到 class 的情况,这样就不那么优雅了:
val action = tableQuery.map{ s => (s.id, trimLeading0(s.name), s.value)}.result
val futureTuples: Future[Seq[(Int, String, Int)]] = db.run(action)
val records = futureTuples map (s => s.map(MyRecord.tupled))
但是如何在构建查询时在 map
方法中执行此操作?或者更改 def name
列描述会更好吗?
您不能乱用 MyTable 中的默认投影(即 def *),因为它需要对称。它用于查询和插入。但是您可以基于 MyTable 的特化创建一个 trimmedTableQuery 并覆盖默认投影。然后,您还可以拥有基于对称默认投影的 tableQuery。如果您尝试基于 trimmedTableQuery 进行插入,则会出现错误(但您不需要这样做,只需使用 tableQuery 进行插入)。
lazy val tableQuery = TableQuery[MyTable]
lazy val trimmedTableQuery = new TableQuery(new MyTable(_) {
override def * = (id, trimLeading0(name), value) <> (MyRecord.tupled, MyRecord.unapply)
})
创建 table 查询时,我想通过映射默认 table 查询来修改我的 select 语句。但是,我找不到一种方法来映射列的值并仍然映射到我的案例 class
case class MyRecord(id: Int, name: String, value: Int)
class MyTable(tag: Tag) extends Table[MyRecord](tag, "MYTABLE") {
def id = column[Int]("id")
def name = column[String]("name")
def value = column[Int]("value")
def * = (id, name, value) <> (MyRecord.tupled, MyRecord.unapply)
}
lazy val tableQuery = TableQuery[MyTable]
我想 trim name
的值与
def trimLeading0: (Rep[String]) => Rep[String] = SimpleExpression.unary[String, String] {
(str, queryBuilder) =>
import slick.util.MacroSupport._
import queryBuilder._
b"TRIM(LEADING 0 FROM $str)"
}
现在我不知道该做什么:
val trimmedTableQuery: Query[MyTable, MyRecord, Seq] = tableQuery.map(s => ???)
我试过映射 Rep
就像处理案例 class:
val trimmedTableQuery = tableQuery.map(s => s.copy(name = trimLeading0(s.name)))
这拒绝使用 value copy is not a member of MyTable
我目前的解决方法是对默认投影使用自定义函数而不是 MyRecord.tupled
:
def trimming(t: (Int, String, Int)) = MyRecord(t._1, t._2.dropWhile(_ == "0"), t._3)
def * = (id, name, value) <> (trimming, MyRecord.unapply)
或者,我可以将返回元组的 DBIOAction
的返回结果映射到 class 的情况,这样就不那么优雅了:
val action = tableQuery.map{ s => (s.id, trimLeading0(s.name), s.value)}.result
val futureTuples: Future[Seq[(Int, String, Int)]] = db.run(action)
val records = futureTuples map (s => s.map(MyRecord.tupled))
但是如何在构建查询时在 map
方法中执行此操作?或者更改 def name
列描述会更好吗?
您不能乱用 MyTable 中的默认投影(即 def *),因为它需要对称。它用于查询和插入。但是您可以基于 MyTable 的特化创建一个 trimmedTableQuery 并覆盖默认投影。然后,您还可以拥有基于对称默认投影的 tableQuery。如果您尝试基于 trimmedTableQuery 进行插入,则会出现错误(但您不需要这样做,只需使用 tableQuery 进行插入)。
lazy val tableQuery = TableQuery[MyTable]
lazy val trimmedTableQuery = new TableQuery(new MyTable(_) {
override def * = (id, trimLeading0(name), value) <> (MyRecord.tupled, MyRecord.unapply)
})