2013-11-28 97 views
4

我的Play應用程序中有超過一百個列查詢數據庫表的方法。我無法爲每個這樣的查詢定義case類,因爲它只是非常大而且必須隨着數據庫上每個表的改變而改變。Slick:使用獲取列名查詢多個表/數據庫

我用這種方法,在查詢的結果,看起來是這樣的:

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實現這一目標?

回答

2
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 
+0

感謝。我認爲它應該是'scala.slick.session.PositionedResult'而不是'scala.slick.jdbc.PositionedResult'?另一個問題 - 如果使用(ResultMap).fistOption',它會陷入無限循環。如果使用'(ResultMap).list',一切都很好。有沒有辦法糾正這個問題? – Caballero

+0

如果在Slick 2.0中仍然存在,請與我們聯繫 – cvogt

+0

我注意到,在查詢'SELECT c AS column1 FROM t'中,結果中列的名稱仍然是'c',尤其是一個大問題用於動態計算的列。有沒有解決方案? – Caballero

0

即(小寫鍵)與not null列產生地圖另一變型:

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 
}) 
相關問題