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

Bro*_*ass 17 scala slick slick-3.0

我正在使用Slick 3.1.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]  
Run Code Online (Sandbox Code Playgroud)

相应的案例类:

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

最后是数据访问查询:

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

我已经考虑并研究了这个(过时的)答案和其他人提出的选项:

  • 有一个不同于默认投影的投影,它会映射到"轻量级版本AuditResult,例如AuditResultLight省略那些列 - 尽管我付出了最大的努力但我无法做到这一点 - 我觉得这应该是正确的方法 - 一旦我有了"工作"投影我仍然有一个光滑的错误"找不到匹配的形状.Slick不知道如何映射给定的类型"
  • 使用抽象AuditResultTableBase类和从中派生的两个类构建一个类层次结构- 一个添加"重"列,另一个不添加它们,两者都有各自的默认投影和案例类.这很好用,但这种方法似乎是错误的,需要一个相对较大的代码更改才能实现这么简单的事情.
  • 实现元组而不是案例类 - 这当然会起作用,但我希望我的数据访问层是强类型的.

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

Woj*_*zyk 8

我有类似的问题!你必须定义形状!在文档的帮助下,我设法使用"轻量级"案例类工作.

首先,定义更简单的类:

case class AuditResultLight(
  ProcessorId: Long,
  DispatchedTimestamp: Timestamp,
  IsSuccessful: Boolean,
  AuditResultId: Long = 0L
)
Run Code Online (Sandbox Code Playgroud)

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

case class AuditResultLightLifted(
  ProcessorId: Rep[Long],
  DispatchedTimestamp: Rep[Timestamp],
  IsSuccessful: Rep[Boolean],
  AuditResultId: Rep[Long]
)
Run Code Online (Sandbox Code Playgroud)

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

implicit object AuditResultLightShape 
  extends CaseClassShape(AuditResultLightLifted.tupled, AuditResultLight.tupled)
Run Code Online (Sandbox Code Playgroud)

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

val auditResultsLight = auditResults.map(r => AuditResultLightLifted(r.ProcessorId, r.DispatchedTimestamp, r.IsSuccessful, r.AuditResultId))  
Run Code Online (Sandbox Code Playgroud)

然后,您可以定义以灯光形式返回失败审核的函数:

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

代码的要点:https://gist.github.com/wjur/93712a51d392d181ab7fc2408e4ce48b

代码编译并执行,但在我的情况下,问题是我的IDE(IntelliJ)报告Query[Nothing, Nothing, scala.Seq]类型auditResultsLight.每当我使用时都会出现语法错误,auditResultsLightAuditResultLight在查询中引用某个字段.但是,正因为如此,我最终决定使用你建议的第二种方法(带有抽象表的方法).几乎相同数量的代码,但支持IDE.