admin

修改列值后将Slick查询映射到默认投影

sql

创建表查询时,我想通过映射默认表查询来修改我的select语句。但是,我找不到映射列值并仍然映射到我的案例类的方法

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]

我想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就像处理case类一样:

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元组的返回结果映射到case类,这不太优雅:

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列说明会更好?


阅读 219

收藏
2021-06-07

共1个答案

admin

您不能弄乱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)
})
2021-06-07