Slick 3.1 - 检索列的子集作为案例 class

Slick 3.1 - Retrieving subset of columns as a case class

我正在使用 Slick 3.1.1,问题是在某些情况下我想省略一些相当重的列,但仍然将该列的子集具体化为一个案例 class。

考虑以下 table 定义:

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]  

对应案例class:

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 和其他人提出的选项:

对于这个问题,Slick 3.1 的惯用/最佳实践是什么?我可以为此使用自定义投影吗?如果可以,对于这个特定示例/查询,SystemAOutputSystemBOutput 是我想省略的重列会是什么样子?

我遇到了类似的问题!你必须定义形状!在 documentation 的帮助下,我设法使 "light" 案例 class 可行。

首先,定义更简单的class:

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

然后,您需要创建案例的提升版本class:

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

此外,您需要一个隐式对象 (Shape) 来告诉 slick 如何将一个映射到另一个:

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

现在,您可以定义一个 returns AuditResultLight 的查询(不完全是投影,但据我所知它的工作方式类似):

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

然后,你可以定义returns审计失败的轻量级函数:

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 的字段时,我都会收到语法错误。但是,因此,最后,我决定使用您建议的第二种方法(带有抽象 table 的方法)。几乎相同数量的代码,但有 IDE 支持。