【问题标题】:Slick: query multiple tables/databases with getting column namesSlick:通过获取列名查询多个表/数据库
【发布时间】:2013-12-14 05:59:51
【问题描述】:

我的 Play 应用中有一些方法可以查询包含一百多列的数据库表。我不能为每个这样的查询定义案例类,因为它会非常大,并且必须随着数据库上表的每次更改而更改。

我正在使用这种方法,查询结果如下所示:

Map(columnName1 -> columnVal1, columnName2 -> columnVal2, ...)

代码示例:

implicit val getListStringResult = GetResult[List[Any]] (
    r => (1 to r.numColumns).map(_ => r.nextObject).toList
)

def getSomething(): Map[String, Any] = DB.withSession {
    val columns = MTable.getTables(None, None, None, None).list.filter(_.name.name == "myTable").head.getColumns.list.map(_.column) 
    val result = sql"""SELECT * FROM myTable LIMIT 1""".as[List[Any]].firstOption.map(columns zip _ toMap).get
}

当查询仅在单个数据库和单个表上运行时,这不是问题。我需要能够在我的查询中使用多个表和数据库,如下所示:

def getSomething(): Map[String, Any] = DB.withSession {

    //The line below is no longer valid because of multiple tables/databases
    val columns = MTable.getTables(None, None, None, None).list.filter(_.name.name == "table1").head.getColumns.list.map(_.column) 
    val result = sql"""
        SELECT      * 
        FROM        db1.table1
        LEFT JOIN   db2.table2 ON db2.table2.col1 = db1.table1.col1
        LIMIT       1
    """.as[List[Any]].firstOption.map(columns zip _ toMap).get

}

不能再使用相同的方法来检索列名。使用 PHP PDO 或 Java JDBCTemplate 之类的东西时,这个问题不存在 - 这些检索列名无需任何额外的努力。

我的问题是:我如何使用 Slick 实现这一目标?

【问题讨论】:

    标签: scala playframework playframework-2.0 slick play-slick


    【解决方案1】:
    import scala.slick.jdbc.{GetResult,PositionedResult}
    object ResultMap extends GetResult[Map[String,Any]] {
      def apply(pr: PositionedResult) = {
        val rs = pr.rs // <- jdbc result set
        val md = rs.getMetaData();
        val res = (1 to pr.numColumns).map{ i=> md.getColumnName(i) -> rs.getObject(i) }.toMap
        pr.nextRow // <- use Slick's advance method to avoid endless loop
        res
      }
    }
    val result = sql"select * from ...".as(ResultMap).firstOption
    

    【讨论】:

    • 谢谢。我认为应该是scala.slick.session.PositionedResult 而不是scala.slick.jdbc.PositionedResult?另一个问题 - 如果使用 as(ResultMap).fistOption - 它会陷入无限循环。如果使用as(ResultMap).list,一切都很好。有没有办法解决这个问题?
    • 如果在 Slick 2.0 中仍然如此,请联系我们
    • 我注意到在查询SELECT c AS column1 FROM t 中,结果中的列名仍然是c,这是一个大问题,尤其是对于动态计算的列。有解决办法吗?
    • 我不明白。这有关系吗?如果是,请解释。否则,请打开一个单独的问题。
    • @cvogt 当查询不返回任何结果时这是如何工作的。我有一个类似的要求,即只从查询中获取列。适用于返回结果的查询,但不适用于没有结果的查询。
    【解决方案2】:

    另一个产生非空列(小写键)的映射的变体:

    private implicit val getMap = GetResult[Map[String, Any]](r => {
        val metadata = r.rs.getMetaData
        (1 to r.numColumns).flatMap(i => {
            val columnName = metadata.getColumnName(i).toLowerCase
            val columnValue = r.nextObjectOption
            columnValue.map(columnName -> _)
        }).toMap
    })
    

    【讨论】:

      猜你喜欢
      • 2011-04-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-04-15
      • 1970-01-01
      • 2015-06-12
      • 2013-10-22
      相关资源
      最近更新 更多