scala SLICK:使用获取列名查询多个表/数据库

2j4z5cfb  于 2022-11-09  发布在  Scala
关注(0)|答案(3)|浏览(210)

在我的Play应用程序中,我有一些方法可以查询包含100多列的数据库表。我不能为每个这样的查询定义CASE类,因为它会大得离谱,并且必须随着数据库上表的每次更改而更改。
我使用这种方法,其中查询结果如下所示:

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

}

同样的方法不能再用于检索列名。当使用像PHPPDO或Java JDBCTemplate这样的东西时,这个问题就不存在了--这些东西不需要任何额外的工作就能检索列名。
我的问题是:我如何使用SLICK实现这一点?

gg58donl

gg58donl1#

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
qhhrdooz

qhhrdooz2#

生成具有非空列(小写的键)的map的另一个变体:

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
})
gywdnpxw

gywdnpxw3#

“正确”答案pr.nextRow // <- use Slick's advance method to avoid endless loop中的字符串是错误的,它只给了var查询结果的一半。

相关问题