光滑2.10-RC1,Scala 2.11.x,绕过22个arity限制与案例类(异类)

时间:2014-07-27 04:54:15

标签: scala slick case-class shapeless

我在映射具有>的表时遇到问题22列专门用于case class,假设您有以下代码

import slick.driver.PostgresDriver
import scala.slick.collection.heterogenous._
import syntax._
import shapeless.Generic

case class TwentyThreeCaseClass(
    val id:Option[Long],
    val one:String,
    val two:String,
    val three:String,
    val four:String,
    val five:String,
    val six:String,
    val seven:String,
    val eight:String,
    val nine:String,
    val ten:String,
    val eleven:String,
    val twelve:String,
    val thirteen:String,
    val fourteen:String,
    val fifteen:String,
    val sixteen:String,
    val seventeen:String,
    val eighteen:String,
    val nineteen:String,
    val twenty:String,
    val twentyOne:String,
    val twentyTwo:String,
    val twentyThree:String,
    val twentyFour:String
)

class TwentyThreeTable(tag:Tag) extends Table[TwentyThreeCaseClass](tag,"twenty_three_table") {
    def id = column[Long]("id",O.PrimaryKey,O.AutoInc)
    def one = column[String]("one")
    def two = column[String]("two")
    def three = column[String]("three")
    def four = column[String]("four")
    def five = column[String]("five")
    def six = column[String]("six")
    def seven = column[String]("seven")
    def eight = column[String]("eight")
    def nine = column[String]("nine")
    def ten = column[String]("ten")
    def eleven = column[String]("eleven")
    def twelve = column[String]("twelve")
    def thirteen = column[String]("thirteen")
    def fourteen = column[String]("fourteen")
    def fifteen = column[String]("fifteen")
    def sixteen = column[String]("sixteen")
    def seventeen = column[String]("seventeen")
    def eighteen = column[String]("eighteen")
    def nineteen = column[String]("nineteen")
    def twenty = column[String]("twenty")
    def twentyOne = column[String]("twentyOne")
    def twentyTwo = column[String]("twentyTwo")
    def twentyThree = column[String]("twentyThree")
    def twentyFour = column[String]("twentyFour")

    private def iso[L <: HList, M <: HList](l: L)
                                 (implicit iso: Generic.Aux[TwentyThreeCaseClass, M], eq: L =:= M): TwentyThreeCaseClass = iso.from(l)

    def * =
        id.? ::
        one ::
        two ::
        three ::
        four ::
        five ::
        six ::
        seven ::
        eight ::
        nine ::
        ten ::
        elven ::
        twelve ::
        thirteen ::
        fourteen ::
        fifteen ::
        sixteen ::
        seventeen ::
        eighteen ::
        nineteen ::
        twenty ::
        twentyOne ::
        twentyTwo ::
        twentyThree ::
        twentyFour ::
        HNil
        // Do stuff here to map to a case class

}

你究竟如何将表格构建/提取到TwentyThreeCaseClass中。示例代码给出了如何将一个光滑的Table映射到HList,但没有给出关于如何将表映射到案例类的代码&gt;通过HList的22个参数(你不能使用元组,因为Scala中的arity限制仍然适用于元组,你不能用二十二个元素组成一个元组)

iso就在那里,因为我们使用这个通用的iso代码从我的无形代码中的HList映射到case class具有相同的形状,所以理论上讲你应该能够使用iso来构造HList的case类,我只是不知道如何在光滑的形状中使用iso

编辑: 这个问题在光滑的github上提出了同样的问题https://github.com/slick/slick/issues/519#issuecomment-48327043

1 个答案:

答案 0 :(得分:8)

想出来,虽然它不是通用的,但它非常丑陋。

def * =
    (id.? ::
    one ::
    two ::
    three ::
    four ::
    five ::
    six ::
    seven ::
    eight ::
    nine ::
    ten ::
    elven ::
    twelve ::
    thirteen ::
    fourteen ::
    fifteen ::
    sixteen ::
    seventeen ::
    eighteen ::
    nineteen ::
    twenty ::
    twentyOne ::
    twentyTwo ::
    twentyThree ::
    twentyFour ::
    HNil).shaped <>
          ({case x => TwentyThreeCaseClass(
            x(0),
            x(1),
            x(2),
            x(3),
            x(4),
            x(5),
            x(6),
            x(7),
            x(8),
            x(9),
            x(10),
            x(11),
            x(12),
            x(13),
            x(14),
            x(15),
            x(16),
            x(17),
            x(18),
            x(19),
            x(20),
            x(21),
            x(22),
            x(23),
            x(24)
            )}, ({x:TwentyThreeCaseClass =>
            Option((
              x.id ::
              x.one ::
              x.two ::
              x.three ::
              x.four ::
              x.five ::
              x.six ::
              x.seven ::
              x.eight ::
              x.nine ::
              x.ten ::
              x.eleven ::
              x.twelve ::
              x.thirteen ::
              x.fourteen ::
              x.fifteen ::
              x.sixteen ::
              x.seventeen ::
              x.eighteen ::
              x.nineteen ::
              x.twenty ::
              x.twentyOne ::
              x.twentyTwo ::
              x.twentyThree ::
              x.twentyFour ::
              HNil
            ))
          }))

事实证明有一些事情

  1. 这与无形无关,Slick使用自己的HList实现(与无形的语法完全相同!)
  2. 据我所知,Slick HList似乎没有任何通用的方法来处理映射到case class之类的东西(从案例类到Slick`HLIst) )
  3. Eiher将光滑Hlist转换为无形HList的库将是方便的,或者是Slick Hlist的通用能力。前者可能是一个更好的选择,因为无形已经比Slick做得更好,而且它可能超出Slicks范围
  4. 做类似

    的事情
    def gen = Generic[TwentyThreeCaseClass]
    ...
    .shaped <>
          ({case x => gen.from(x)}, {TwentyThreeCaseClass => Option(gen.to(x))})
    

    会更理想

    这是另一个例子

    https://github.com/playframework/play-slick/issues/214