scala slick slick-3.0

scala - Slick 3.1-Recuperando subconjunto de columnas como una clase de caso



slick-3.0 (1)

¡Tuve un problema similar! Tienes que definir la Forma! Con la ayuda de la documentation , logré que el enfoque funcionara con una clase de caso "ligera".

Primero, define la clase más simple:

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

Luego, necesita crear una versión elevada de la clase de caso:

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

Además, necesita un objeto implícito ( la Forma ) para indicar a Slick cómo asignar uno a otro:

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

Ahora, puede definir una consulta que devuelva AuditResultLight (no es exactamente una proyección, pero, según tengo entendido, funciona de manera similar):

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

Luego, puede definir la función que devuelve las auditorías fallidas en forma ligera:

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

Un resumen con el código: https://gist.github.com/wjur/93712a51d392d181ab7fc2408e4ce48b

El código compila y ejecuta, pero en mi caso, el problema es que mi IDE (IntelliJ) informa el tipo de Query[Nothing, Nothing, scala.Seq] para auditResultsLight . Recibo errores de sintaxis cuando uso auditResultsLight y me refiero a un campo de AuditResultLight en una consulta. Sin embargo, debido a eso, al final, decidí usar el segundo enfoque que sugirió (el que tiene una tabla abstracta). Casi la misma cantidad de código, pero con soporte IDE.

Estoy trabajando con Slick 3.1.1 y el problema es que, en algunos casos, quiero omitir algunas columnas que son bastante pesadas y aún así materializar ese subconjunto de columnas como una clase de caso.

Considere la siguiente definición de tabla:

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]

La clase de caso correspondiente:

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

Y finalmente la consulta de acceso a datos:

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

He considerado y examinado las opciones presentadas en esta respuesta (obsoleta) y otras:

  • Tener una proyección diferente a la proyección predeterminada que se asigna a una "versión ligera de AuditResult , por ejemplo, AuditResultLight que omite esas columnas, a pesar de mi mejor esfuerzo, no pude hacer que esto funcione. Creo que este debería ser el enfoque correcto, una vez que tuve una proyección "en funcionamiento" Todavía tengo un error Slick "No se encontró una forma que coincida. Slick no sabe cómo mapear los tipos dados "
  • Construyendo una jerarquía de clases con una clase AuditResultTableBase abstracta y dos clases que derivan de ella, una que agrega las columnas "pesadas" y una sin ellas, ambas con sus respectivas clases de proyección y caso predeterminadas. Esto funciona bien, pero el enfoque parece incorrecto y requiere un cambio de código relativamente grande para algo tan fácil.
  • Materializar tuplas en lugar de clases de casos: esto, por supuesto, funcionaría, pero quiero que mi capa de acceso a datos se escriba con fuerza.

¿Cuál es la mejor práctica / idiomática de Slick 3.1 para este problema? ¿Puedo usar una proyección personalizada para esto y, de ser así, qué aspecto tendría este ejemplo / consulta en particular con SystemAOutput y SystemBOutput como las columnas pesadas que quiero omitir?