从表中访问数据库列名?

时间:2013-11-15 00:55:37

标签: scala slick

我们说a table

object Suppliers extends Table[(Int, String, String, String)]("SUPPLIERS") {
  def id = column[Int]("SUP_ID", O.PrimaryKey)
  def name = column[String]("SUP_NAME")
  def state = column[String]("STATE")
  def zip = column[String]("ZIP")
  def * = id ~ name ~ state ~ zip
}

表的数据库名称

可以通过以下方式访问表格的数据库名称:Suppliers.tableName
Scaladoc on AbstractTable支持此功能。

例如,上表的数据库名称为" SUPPLIERS"。

列'数据库名称

通过AbstractTablegetLinearizedNodesindexes看起来很有希望。但是,字符串表示中没有列名称。

我认为*表示"all the columns I'm usually interested in." *MappedProjection,具有此签名:

final case class MappedProjection[T, P <: Product](
  child: Node, 
  f: (P) ⇒ T, 
  g: (T) ⇒ Option[P])(proj: Projection[P]) 
extends ColumnBase[T] with UnaryNode with Product with Serializable

*.getLinearizedNodes包含大量数字,我意识到此时我只是对API中的所有内容进行强力检查,以便可能在字符串中找到列名。

之前有没有人遇到过这个问题,或者有人能让我更好地了解MappedProjection的工作原理吗?

3 个答案:

答案 0 :(得分:3)

它需要您依赖Slick内部,这可能会在版本之间发生变化,但这是可能的。以下是它对Slick 1.0.1的工作原理:您必须通过FieldSymbol。然后,您可以提取所需的信息,例如columnInfo(driver: JdbcDriver, column: FieldSymbol): ColumnInfo如何做。

要从FieldSymbol获取Column,您可以使用fieldSym(node: Node): Option[FieldSymbol]fieldSym(column: Column[_]): FieldSymbol

答案 1 :(得分:2)

要获取(合格)列名称,您只需执行以下操作:

Suppliers.id.toString
Suppliers.name.toString
Suppliers.state.toString
Suppliers.zip.toString

toString将产生列名称的任何地方都没有明确说明,因此您的问题是有效的。


现在,如果你想以编程方式获取所有列名,那就更难了。您可以尝试使用反射来获取返回Column[_]并在其上调用toString的所有方法,但这不会很优雅。或者你可以破解一下,从这样的查询中获取select * SQL语句:

val selectStatement = DB withSession {
  Query(Suppliers).selectStatement
}

然后解析我们的列名。

这是我能做的最好的事情。如果有人知道更好的方式,请分享 - 我也很感兴趣;)

答案 2 :(得分:2)

代码基于Lightbend Activator&#34; slick-http-app&#34;。

光滑版本:3.1.1

将此方法添加到BaseDal:

def getColumns(): mutable.Map[String, Type] = {
  val columns = mutable.Map.empty[String, Type]

  def selectType(t: Any): Option[Any] = t match {
    case t: TableExpansion => Some(t.columns)
    case t: Select => Some(t.field)
    case _ => None
  }
  def selectArray(t:Any): Option[ConstArray[Node]] = t match {
    case t: TypeMapping => Some(t.child.children)
    case _ => None
  }
  def selectFieldSymbol(t:Any): Option[FieldSymbol] = t match {
    case t: FieldSymbol => Some(t)
    case _ => None
  }

  val t = selectType(tableQ.toNode)
  val c = selectArray(t.get)

  for (se <- c.get) {
    val col = selectType(se)
    val fs = selectFieldSymbol(col.get)
    columns += (fs.get.name -> fs.get.tpe)
  }
  columns
}

此方法从TableQ获取列名(DB中的实名)+类型

使用的进口是:

     import slick.ast._
     import slick.util.ConstArray