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 和其他人提出的选项:
- 与映射到 "light version of the
AuditResult
, e.g. AuditResultLight
that omits those columns - despite my best effort I couldn't make this work - I feel like this should be the right approach - once I had a "working" 投影的默认投影不同,我仍然遇到 Slick 错误 "No matching Shape found. Slick does not know how to map the given types"
- 构建一个 class 层次结构,其中包含抽象
AuditResultTableBase
class 和两个从中派生的 classes - 一个添加 "heavy" 列和一个没有它们,都有各自的默认投影和大小写 classes。这工作得很好,但这种方法似乎是错误的,需要相对较大的代码更改才能实现如此简单的事情。
- 具体化元组而不是大小写 classes - 这当然可行,但我希望我的数据访问层是强类型的。
对于这个问题,Slick 3.1 的惯用/最佳实践是什么?我可以为此使用自定义投影吗?如果可以,对于这个特定示例/查询,SystemAOutput
和 SystemBOutput
是我想省略的重列会是什么样子?
我遇到了类似的问题!你必须定义形状!在 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 支持。
我正在使用 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 和其他人提出的选项:
- 与映射到 "light version of the
AuditResult
, e.g.AuditResultLight
that omits those columns - despite my best effort I couldn't make this work - I feel like this should be the right approach - once I had a "working" 投影的默认投影不同,我仍然遇到 Slick 错误 "No matching Shape found. Slick does not know how to map the given types" - 构建一个 class 层次结构,其中包含抽象
AuditResultTableBase
class 和两个从中派生的 classes - 一个添加 "heavy" 列和一个没有它们,都有各自的默认投影和大小写 classes。这工作得很好,但这种方法似乎是错误的,需要相对较大的代码更改才能实现如此简单的事情。 - 具体化元组而不是大小写 classes - 这当然可行,但我希望我的数据访问层是强类型的。
对于这个问题,Slick 3.1 的惯用/最佳实践是什么?我可以为此使用自定义投影吗?如果可以,对于这个特定示例/查询,SystemAOutput
和 SystemBOutput
是我想省略的重列会是什么样子?
我遇到了类似的问题!你必须定义形状!在 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 支持。