2016-09-29 37 views
16

我用油滑3.1.1和問題的工作是,在某些情況下,我想省略一些列是相當沉重的,仍然兌現列的子集作爲案例分類。油滑3.1 - 檢索列的子集作爲一個案例類

考慮下面的表定義:

class AuditResultTable(tag: Tag) extends Table[AuditResult](tag, AuditResultTableName) { 
    def auditResultId: Rep[Long] = column[Long]("AuditResultId", O.PrimaryKey, O.AutoInc) 
    def processorId: Rep[Long] = column[Long]("ProcessorId") 
    def dispatchedTimestamp: Rep[Timestamp] = column[Timestamp]("DispatchedTimestamp", O.SqlType("timestamp(2)")) 
    def SystemAOutput: Rep[Array[Byte]] = column[Array[Byte]]("SystemAOutput", O.SqlType("LONGBLOB")) 
    def SystemBOutput: Rep[Array[Byte]] = column[Array[Byte]]("SystemBOutput", O.SqlType("LONGBLOB")) 
    def isSuccessful: Rep[Boolean] = column[Boolean]("IsSuccessful") 


def * : ProvenShape[AuditResult] = (processorId, dispatchedTimestamp, systemAOutput, systemBOutput, isSuccessful, auditResultId) <> 
    (AuditResult.tupled, AuditResult.unapply) 

} 

val auditResults = TableQuery[AuditResultTable] 

相應的案例類:

case class AuditResult (
    ProcessorId: Long, 
    DispatchedTimestamp: Timestamp, 
    SystemAOutput: Array[Byte], 
    SystemBOutput: Array[Byte], 
    IsSuccessful: Boolean, 
    AuditResultId: Long = 0L 
) 

最後的數據訪問查詢:

def getRecentFailedAuditsQuery(): Query[AuditResultTable, AuditResult, Seq] = { 
    auditResults.filterNot(r => r.isSuccessful) 
} 

我考慮過,看着出現的選項in this (outdated) answer和其他:

  • 具有與映射到「AuditResult的輕版本」的默認投影不同的投影,例如, AuditResultLight省略了這些列 - 儘管我不能做這樣的工作,我最大的努力 - 我覺得這應該是正確的做法 - 我曾有過一個「工作」的投影我還有一個漂亮的錯誤「找不到匹配的形狀。油滑不知道如何映射「,從它派生
  • 建設類層次結構與抽象AuditResultTableBase類兩大類 - 一個,增加了‘給定類型的重磅’列和一個沒有他們,都與各自的默認的投影和案例分類。這很好地工作,但這種方法似乎是錯誤的,並且需要對這樣一個簡單的事情進行相對較大的代碼更改。
  • 物化元組,而不是case類 - 這當然會的工作,但我想是強類型我的數據訪問層。

對於這個問題,Slick 3.1的慣用/最佳實踐是什麼?我可以使用自定義投影此,如果這樣你會看起來像這個特殊的例子/查詢與SystemAOutputSystemBOutput是重列我想省略?

回答

5

我有一個類似的問題!你必須定義形狀!在documentation的幫助下,我設法通過一個「輕量級」的課堂作業來實現這一方法。

首先,定義簡單的類:

case class AuditResultLight(
    ProcessorId: Long, 
    DispatchedTimestamp: Timestamp, 
    IsSuccessful: Boolean, 
    AuditResultId: Long = 0L 
) 

然後,你需要創建的情況下類的解除版本:

case class AuditResultLightLifted(
    ProcessorId: Rep[Long], 
    DispatchedTimestamp: Rep[Timestamp], 
    IsSuccessful: Rep[Boolean], 
    AuditResultId: Rep[Long] 
) 

另外,你需要一個隱含的對象(形狀)告訴光滑如何映射一個到另一個:

implicit object AuditResultLightShape 
    extends CaseClassShape(AuditResultLightLifted.tupled, AuditResultLight.tupled) 

現在,您可以定義返回AuditResultLight查詢(不完全是一個投影,但據我瞭解它的工作原理類似):

val auditResultsLight = auditResults.map(r => AuditResultLightLifted(r.ProcessorId, r.DispatchedTimestamp, r.IsSuccessful, r.AuditResultId)) 

然後,您可以定義返回光的形式失敗的審覈功能:

def getRecentFailedAuditsQuery(): Query[AuditResultTable, AuditResultLight, Seq] = { 
    auditResultsLight.filterNot(r => r.isSuccessful) 
} 

與代碼中的要點是:https://gist.github.com/wjur/93712a51d392d181ab7fc2408e4ce48b

的代碼編譯和執行,但對我來說,這個問題是我的IDE(的IntelliJ)報告Query[Nothing, Nothing, scala.Seq]類型auditResultsLight。無論何時使用auditResultsLight並在查詢中引用AuditResultLight字段,我都會收到語法錯誤。然而,正因爲如此,我最終決定使用你提出的第二種方法(帶有抽象表格的那種方法)。幾乎相同數量的代碼,但具有IDE支持。

+0

謝謝Wojciech--我本來希望能有一個明確正確的答案,但似乎我不是唯一有問題的人。感謝有關如何正確實現此用例的形狀/映射的知識(即使IntelliJ不喜歡它) - 賞金是你的全部。 – BrokenGlass