2016-09-29 43 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