在 Slick table 上列出列

Listing columns on a Slick table

我有一个类似于以下的 Slick 3.0 table 定义:

case class Simple(a: String, b: Int, c: Option[String])

trait Tables { this: JdbcDriver =>
  import api._

  class Simples(tag: Tag) extends Table[Simple](tag, "simples") {
    def a = column[String]("a")
    def b = column[Int]("b")
    def c = column[Option[String]]("c")

    def * = (a, b, c) <> (Simple.tupled, Simple.unapply)
  }

  lazy val simples = TableQuery[Simples]

} 

object DB extends Tables with MyJdbcDriver

我希望能够做两件事:

  1. 获取列名列表为Seq[String]
  2. 对于 Simple 的实例,生成一个 Seq[String] 对应于使用原始查询将数据插入数据库的方式(例如 Simple("hello", 1, None) 变为 Seq("'hello'", "1", "NULL"))

使用 Slick table 定义执行此操作的最佳方法是什么?

要获取列名,试试这个:

db.run(for {
       metaTables <- slick.jdbc.meta.MTable.getTables("simples")
       columns <- metaTables.head.getColumns
       } yield columns.map {_.name}) foreach println

这将打印

Vector(a, b, c)

对于 class 个值,您可以使用 productIterator:

Simple("hello", 1, None).productIterator.toVector

Vector(hello, 1, None)

还是要做值映射,保证table中列的顺序和class中的值是一样的

  • 首先,在不改变 [=12= 中值的顺序的情况下,不可能欺骗 Slick 并改变 * 方法中 <> 运算符左侧的顺序],Simples 的行类型,即 Ben 假设的不可能。 * 投影方法的 ProvenShape return 类型确保有一个 Shape 可用于在 * 中基于 Column 的类型和客户端-侧类型,如果你写 def * = (c, b, a) <> Simple.tupled, Simple.unapply) 将 Simple 定义为 case class Simple(a: String, b: Int, c: Option[String]),Slick 会报错 "No matching Shape found. Slick does not know how to map the given types..."。因此,您可以使用 productIterator.
  • 迭代 Simple 实例的所有元素
  • 其次,您已经在代码中定义了 Simples table 并且查询元tables 来获取您已有的相同信息是不明智的。您可以使用一行 simples.baseTableRow.create_*.map(_.name) 获取所有列名称。请注意,table 的 * 投影还定义了在创建 table 架构时生成的列。因此,不会创建投影中未提及的列,并且保证上面的语句 return 正是您所需要的,不会丢失任何东西。

简要回顾一下:

  1. 要获取 Simples table 作为 Seq[String] 的列名列表,请使用 simples.baseTableRow.create_*.map(_.name).toSeq
  2. 生成一个 Seq[String] 对应于数据的方式 将使用 aSimple 的原始查询插入到数据库中, Simple 的实例使用 aSimple.productIterator.toSeq