我正在使用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]
对应的案例类:
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
)相对应,而忽略了这些列-尽管尽我最大的努力,我仍然无法完成这项工作-我觉得这应该是正确的方法-投影完成后,仍然出现Slick错误“找不到匹配的Shape。 Slick不知道如何映射给定的类型”用抽象的
AuditResultTableBase
类和派生自其的两个类构建一个类层次结构-一个添加“重载”列,一个不添加“重载”列,分别具有各自的默认投影类和案例类。这很好用,但是这种方法似乎是错误的,并且需要相对较大的代码更改才能做到这一点。实现元组而不是案例类-这当然可以,但是我希望我的数据访问层是强类型的。
对于此问题,Slick 3.1的惯用/最佳实践是什么?我可以为此使用自定义投影吗?如果是这样,对于此特定示例/查询,
SystemAOutput
和SystemBOutput
是我要忽略的较重的列,会是什么样?
最佳答案
我有类似的问题!您必须定义形状!在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]
)
另外,您需要一个隐式对象(Shape)来告诉滑模如何将一个映射到另一个:
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支持。
关于scala - Slick 3.1-将列的子集作为案例类检索,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39781193/