在 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
我希望能够做两件事:
- 获取列名列表为
Seq[String]
- 对于
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 正是您所需要的,不会丢失任何东西。
简要回顾一下:
- 要获取 Simples table 作为
Seq[String]
的列名列表,请使用
simples.baseTableRow.create_*.map(_.name).toSeq
- 生成一个
Seq[String]
对应于数据的方式
将使用 aSimple
的原始查询插入到数据库中,
Simple
的实例使用 aSimple.productIterator.toSeq
我有一个类似于以下的 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
我希望能够做两件事:
- 获取列名列表为
Seq[String]
- 对于
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 正是您所需要的,不会丢失任何东西。
简要回顾一下:
- 要获取 Simples table 作为
Seq[String]
的列名列表,请使用simples.baseTableRow.create_*.map(_.name).toSeq
- 生成一个
Seq[String]
对应于数据的方式 将使用aSimple
的原始查询插入到数据库中,Simple
的实例使用aSimple.productIterator.toSeq