试图制作一个HCons List CaseClassShape

时间:2016-11-11 07:42:34

标签: scala slick

好的,所以我想创建一个HListCaseClassShape,让我创建克服22个arity限制的case类。所以,从Stefan Zeiger的代码here开始。

final class HListShape[Level <: ShapeLevel, M <: HList, U <: HList : ClassTag, P <: HList](val shapes: Seq[Shape[_, _, _, _]]) extends MappedScalaProductShape[Level, HList, M, U, P] {
    def buildValue(elems: IndexedSeq[Any]) = elems.foldRight(HNil: HList)(_ :: _)
    def copy(shapes: Seq[Shape[_ <: ShapeLevel, _, _, _]]) = new HListShape(shapes)
}
implicit def hnilShape[Level <: ShapeLevel] = new HListShape[Level, HNil.type, HNil.type, HNil.type](Nil)
implicit def hconsShape[Level <: ShapeLevel, M1, M2 <: HList, U1, U2 <: HList, P1, P2 <: HList](implicit s1: Shape[_ <: Level, M1, U1, P1], s2: HListShape[_ <: Level, M2, U2, P2]) =
    new HListShape[Level, M1 :: M2, U1 :: U2, P1 :: P2](s1 +: s2.shapes)

然后我继续创建我的HListCaseClassShape:

class HListCaseClassShape[P <: Product, LiftedList, LiftedCaseClass <: P, PlainList, PlainCaseClass <: P](
       mapLifted: LiftedList => LiftedCaseClass, mapPlain: PlainList => PlainCaseClass)(
       implicit columnShapes: Shape[FlatShapeLevel, LiftedList, PlainList, LiftedList], classTag: ClassTag[PlainCaseClass])
  extends MappedScalaProductShape[FlatShapeLevel, P, LiftedCaseClass, PlainCaseClass, LiftedCaseClass] {
  val shapes = columnShapes.asInstanceOf[HListShape[_,_,_,_]].shapes
  override def toMapped(v: Any) = {
    val folded = v.asInstanceOf[Product].productIterator.foldRight(HNil: HList)(_ :: _)
    folded.asInstanceOf[PlainList]
  }
  def buildValue(elems: IndexedSeq[Any]) = {
    val list = elems.foldRight(HNil: HList)(_ :: _)
    mapLifted(list.asInstanceOf[LiftedList])
  }
  def copy(s: Seq[Shape[_ <: ShapeLevel, _, _, _]]) = new HListCaseClassShape(mapLifted, mapPlain) { override val shapes = s }
}

最后,我尝试将其实例化

case class LiftedB(data1: Rep[String], data2: Rep[String], data3: Rep[String], data4: Rep[String], data5: Rep[String], data6: Rep[String], data7: Rep[String], data8: Rep[String], data9: Rep[String], data10: Rep[String], data11: Rep[String], data12: Rep[String], data13: Rep[String], data14: Rep[String], data15: Rep[String], data16: Rep[String], data17: Rep[String], data18: Rep[String], data19: Rep[String], data20: Rep[String], data21: Rep[String], data22: Rep[String], data23: Rep[String], data24: Rep[String], data25: Rep[String])
case class B(data1: String, data2: String, data3: String, data4: String, data5: String, data6: String, data7: String, data8: String, data9: String, data10: String, data11: String, data12: String, data13: String, data14: String, data15: String, data16: String, data17: String, data18: String, data19: String, data20: String, data21: String, data22: String, data23: String, data24: String, data25: String )

...然后是形状:

type DirectConsList = HCons[String, HCons[String, HCons[String, HCons[String, HCons[String, HCons[String, HCons[String, HCons[String, HCons[String, HCons[String, HCons[String, HCons[String, HCons[String, HCons[String, HCons[String, HCons[String, HCons[String, HCons[String, HCons[String, HCons[String, HCons[String, HCons[String, HCons[String, HCons[String, HCons[String, HNil]]]]]]]]]]]]]]]]]]]]]]]]]
type LiftedConsList = HCons[Rep[String], HCons[Rep[String], HCons[Rep[String], HCons[Rep[String], HCons[Rep[String], HCons[Rep[String], HCons[Rep[String], HCons[Rep[String], HCons[Rep[String], HCons[Rep[String], HCons[Rep[String], HCons[Rep[String], HCons[Rep[String], HCons[Rep[String], HCons[Rep[String], HCons[Rep[String], HCons[Rep[String], HCons[Rep[String], HCons[Rep[String], HCons[Rep[String], HCons[Rep[String], HCons[Rep[String], HCons[Rep[String], HCons[Rep[String], HCons[Rep[String], HNil]]]]]]]]]]]]]]]]]]]]]]]]]

implicit object BShape extends HListCaseClassShape[
  Product,
  LiftedConsList,
  LiftedB,
  DirectConsList,
  B](toLifted, toDirect)

def toLifted(list: LiftedConsList) = {
  list match {
    case data1 :: data2 :: data3 :: data4 :: data5 :: data6 :: data7 :: data8 :: data9 :: data10 :: data11 :: data12 :: data13 :: data14 :: data15 :: data16 :: data17 :: data18 :: data19 :: data20 :: data21 :: data22 :: data23 :: data24 :: data25 :: HNil => {
      LiftedB(data1, data2, data3, data4, data5, data6, data7, data8, data9, data10, data11, data12, data13, data14, data15, data16, data17, data18, data19, data20, data21, data22, data23, data24, data25 )
    }
    case _ => throw new Exception("malformed HList")
  }
}

def toDirect(list:DirectConsList) = {
  list match {
    case data1 :: data2 :: data3 :: data4 :: data5 :: data6 :: data7 :: data8 :: data9 :: data10 :: data11 :: data12 :: data13 :: data14 :: data15 :: data16 :: data17 :: data18 :: data19 :: data20 :: data21 :: data22 :: data23 :: data24 :: data25 :: HNil => {
      B(data1, data2, data3, data4, data5, data6, data7, data8, data9, data10, data11, data12, data13, data14, data15, data16, data17, data18, data19, data20, data21, data22, data23, data24, data25 )
    }
    case _ => throw new Exception("malformed HList")
  }
}

只有当我通过db.stream实例化并运行它才会抛出异常:

Exception in thread "main" java.lang.ClassCastException: slick.collection.heterogeneous.HCons cannot be cast to com.example.CaseClassShapeQueryExample$B
  at com.example.CaseClassShapeQueryExample$$anonfun$2.apply(CaseClassShapeQueryExample.scala:106)
  at slick.backend.DatabasePublisher$$anon$3$$anonfun$onNext$1.apply(DatabasePublisher.scala:48)
  at scala.concurrent.impl.Future$PromiseCompletingRunnable.liftedTree1$1(Future.scala:24)

所以它得到了从查询中返回的普通元组对象(即DirectConsList),但我无法将其转换为B对象。我做错了什么???

1 个答案:

答案 0 :(得分:0)

mapPlain(folded.asInstanceOf[PlainList])方法中,我所遗漏的所有内容都是toMapped。工作HListCaseClassShape的实现如下:

class HListCaseClassShape[P <: Product, LiftedList, LiftedCaseClass <: P, PlainList, PlainCaseClass <: P](
       mapLifted: LiftedList => LiftedCaseClass, mapPlain: PlainList => PlainCaseClass)(
       implicit columnShapes: Shape[FlatShapeLevel, LiftedList, PlainList, LiftedList], classTag: ClassTag[PlainCaseClass])
  extends MappedScalaProductShape[FlatShapeLevel, P, LiftedCaseClass, PlainCaseClass, LiftedCaseClass] {
  val shapes = columnShapes.asInstanceOf[HListShape[_,_,_,_]].shapes
  override def toMapped(v: Any) = {
    val folded = v.asInstanceOf[Product].productIterator.foldRight(HNil: HList)(_ :: _)
    mapPlain(folded.asInstanceOf[PlainList])
  }
  def buildValue(elems: IndexedSeq[Any]) = {
    val list = elems.foldRight(HNil: HList)(_ :: _)
    mapLifted(list.asInstanceOf[LiftedList])
  }
  def copy(s: Seq[Shape[_ <: ShapeLevel, _, _, _]]) = new HListCaseClassShape(mapLifted, mapPlain) { override val shapes = s }
}

另外,要点:Apple's docs