Slick 2.10-RC1,Scala 2.11.x,使用 case 类绕过 22 arity 限制(异构) [英] Slick 2.10-RC1, Scala 2.11.x, bypassing 22 arity limit with case class (heterogenous)

查看:41
本文介绍了Slick 2.10-RC1,Scala 2.11.x,使用 case 类绕过 22 arity 限制(异构)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

import slick.driver.PostgresDriver导入 scala.slick.collection.heterogenous._导入语法._导入 shapeless.Generic案例类TwentyThreeCaseClass(val id:Option[Long],第一个:字符串,值二:字符串,值三:字符串,第四值:字符串,值五:字符串,值六:字符串,值七:字符串,值八:字符串,值九:字符串,值十:字符串,价值十一:字符串,值十二:字符串,第十三值:字符串,第十四值:字符串,值十五:字符串,值十六:字符串,第十七值:字符串,值十八:字符串,值十九:字符串,第二十:字符串,val二十一:字符串,val 二十二:字符串,val二十三:字符串,值二十四:字符串)class TwoThreeTable(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]("二")def 三 = column[String]("三")def四 = column[String]("四")def 五 = column[String]("五")def 6 = column[String]("6")def七 = column[String]("七")def八 = column[String]("八")def九 = column[String]("九")def十 = column[String]("十")def 十一 = column[String]("十一")def十二 = column[String]("十二")def十三 = column[String]("十三")deffourteen = column[String]("十四")def十五 = column[String]("十五")def 十六 = 列[字符串]("十六")def Seventeen = column[String]("十七")def十八 = column[String]("十八")def 十九 = column[String]("十九")def二十 = column[String]("二十")def二十一=列[字符串](二十一")def twoTwo = column[String]("twentyTwo")def twoThree = column[String]("twentyThree")def二十四 = column[String]("twentyFour")private def iso[L <: HList, M <: HList](l: L)(隐式iso:Generic.Aux[TwentyThreeCaseClass, M],eq:L =:= M):TwentyThreeCaseClass = iso.from(l)定义 * =ID.?::一 ::二 ::三 ::四::五 ::六 ::七 ::八 ::九 ::十::精灵::十二::十三::十四 ::十五::十六::十七::十八::十九::二十::21 ::22 ::23 ::二十四 ::HNil//在这里做一些事情来映射到一个案例类}

您将如何将表构建/提取到 TwentyThreeCaseClass 中.示例代码提供了如何将光滑的 Table 映射到 HList,但没有给出如何通过 HList 将 Table 映射到案例类 > 22 个参数的代码> (你不能使用元组,因为 Scala 中的元数限制仍然适用于元组,你不能创建超过 22 个元素的元组)

iso 就在那里,因为我们使用这个通用的 iso 代码从 HList 映射到 case class我们在光滑之外的无形代码,所以从理论上讲,您应该能够使用 iso 从 HList 构造案例类,我只是不知道如何在光滑形状的上下文中使用 iso

在 slick github 上提出了相同的问题作为这里的问题 https://github.com/slick/slick/issues/519#issuecomment-48327043

解决方案

想通了,虽然不通用,但还是很丑.

def * =(ID.? ::一 ::二 ::三 ::四::五 ::六 ::七 ::八 ::九 ::十::精灵::十二::十三::十四 ::十五::十六::十七::十八::十九::二十::21 ::22 ::23 ::二十四 ::HNil).形<>({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 =>选项((x.id ::x.一::x.二::x.三::x.四::x.五::x.6 ::x.7 ::x.8 ::x.九::十::十一点::x.12 ::x.十三::x.十四::X.十五::x.16 ::x.十七::x.十八::x.19 ::x.二十::x.twentyOne ::x.twentyTwo ::x.二十三::x.二十四::HNil))}))

事实证明有一些事情

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

做类似的事情

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

会更理想

这里还有一个例子

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

I am having issues in mapping a Table that has > 22 columns specifically into a case class, assuming you have the following code

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

}

How exactly would you go about constructing/extracting the table into the TwentyThreeCaseClass. Example code is given on how to make a slick Table map to a HList, but code is not given on how to map a Table to a case class > 22 parameters via a HList (you can't use tuples, because the arity limit in Scala still applies for tuples, you can't make a tuple with more then twenty two elements)

The iso is there, because we use this generic iso code to map from a HList to a case class with the same shape in our shapeless code outside of slick, so theoretically speaking you should be able to use iso to construct the case class from the HList, i just have no idea how to use iso in the context of slick shapes

EDIT: There is the same question asked on the slick github as an issue here https://github.com/slick/slick/issues/519#issuecomment-48327043

解决方案

Figured it out, its pretty ugly though since its not generic.

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
            ))
          }))

It turns out there are a few things

  1. This has nothing to do with shapeless, Slick uses its own HList implementation (which has the exact same syntax as shapeless!)
  2. As far as I am aware, Slick HList doesn't appear to have any generic methods for dealing with stuff like mapping to a case class (and going from a case class to a Slick `HLIst)
  3. Eiher a library that converts Slick Hlist to a shapeless HList would be handy, or generic abilities for Slick Hlist. The former may be a better option because shapeless already does generic stuff much better than Slick, and it may be out of Slicks scope

Doing something like

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

Would be much more ideal

here is another example as well

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

这篇关于Slick 2.10-RC1,Scala 2.11.x,使用 case 类绕过 22 arity 限制(异构)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆