在Slick表上列出列

时间:2015-09-19 21:38:48

标签: scala slick

我有一个类似于以下内容的Slick 3.0表定义:

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")变为let config = NSURLSessionConfiguration.ephemeralSessionConfiguration() config.URLCache = nil // don't cache let task = NSURLSession(configuration: config).dataTaskWithURL(...
  3. 使用Slick表定义执行此操作的最佳方法是什么?

2 个答案:

答案 0 :(得分:7)

  • 首先,无法在<>方法中使用Slick并更改*运算符左侧的顺序而不更改Simple中的值的顺序, Simples的行类型,即Ben认为不可能的行。 ProvenShape投影方法的*返回类型可确保Shape可用于在基于Column的*和客户端类型之间进行转换,如果你写简单定义为def * = (c, b, a) <> Simple.tupled, Simple.unapply)的{​​{1}},Slick会抱怨错误“找不到匹配的形状.Slick不知道如何映射给定的类型......”。因此,您可以使用 case class Simple(a: String, b: Int, c: Option[String]) 迭代Simple实例的所有元素。
  • 其次,您已经在代码中定义了productIterator表,并查询元数据以获取您已有的相同信息是不明智的。您可以使用单行 Simples 获取所有列名称。请注意,表的simples.baseTableRow.create_*.map(_.name)投影还定义了创建表模式时生成的列。因此,不会创建投影中未提及的列,并且上述语句可以保证准确返回您所需的内容而不会丢弃任何内容。

简要回顾一下:

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

答案 1 :(得分:1)

要获取列名称,请尝试以下操作:

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

这将打印

Vector(a, b, c)

对于案例类值,您可以使用productIterator:

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

Vector(hello, 1, None)

您仍然需要进行值映射,并保证表中列的顺序和case类中的值相同。