【问题标题】:Playframework and Scala Slick tuple with more than 22 fields具有超过 22 个字段的 Playframework 和 Scala Slick 元组
【发布时间】:2020-09-17 21:50:03
【问题描述】:

我的案例类大约有 26 个数据库字段,但在 scala 和/或 Scala Slick 中存在 22 个字段的限制。

有没有办法打破这个限制?

我试过这个:Slick codegen & tables with > 22 columns

没有任何好的结果^^

提前致谢。

更新:

我尝试了该示例,但出现错误...

我的代码如下所示:

package dto.regulations.models

import ai.x.play.json.Jsonx
import dto.client.models.{PriceCategoriesModel, SlaLevelsModel}
import dto.crawler.models.{CrawlerModel, CrawlerUrlsModel, ResultsCrawlerModel}
import play.api.db.slick.HasDatabaseConfigProvider
import play.api.libs.json._
import slick.jdbc.JdbcProfile
import slick.lifted.ProvenShape

import slick.jdbc.H2Profile.api._
import shapeless._
import slickless._

case class RegulationModel(
                            regulationId: Option[Int] = None,
                            name: String,
                            [.... some other attributes....]
                            // Non Database fields
                            priceCategory: Option[PriceCategoriesModel]  = None,
                            slaLevel: Option[SlaLevelsModel]  = None,

                            markets: Option[Seq[MarketsModel]] = None,
                            tags: Option[Seq[TagsModel]]  = None,
                            crawler: Option[CrawlerModel]  = None,
                            commentCreatedAt: Option[String]  = None,
                            creatorComment: Option[String]  = None,
                            approved: Option[Boolean]  = None,
                            approverComment: Option[String],
                            approvedAt: Option[String],
                            creatorUuid: Option[String],
                            approverUuid: Option[String],

                            regulationPackages: Option[Seq[RegulationPackagesModel]],
                            regulation_Evaluations: Option[Seq[Regulation_EvaluationModel]]
                          ) {
  def toApi: RegulationApi = RegulationApi.fromModel(this)
}


object RegulationModel {
  implicit val regulationFormat: OFormat[RegulationModel] = Jsonx.formatCaseClass[RegulationModel]
}


case class RegulationApi(
                          regulationId: Option[Int] = None,
                          name: String,
                          description: Option[String],

                              [.... some other attributes....]


                          // Non Database fields
                          priceCategory: Option[PriceCategoriesModel],
                          slaLevel: Option[SlaLevelsModel],

                          markets: Option[Seq[MarketsModel]],
                          tags: Option[Seq[TagsModel]],
                          crawler: Option[CrawlerModel],

                          commentCreatedAt: Option[String],
                          creatorComment: Option[String],
                          approved: Option[Boolean],
                          approverComment: Option[String],
                          approvedAt: Option[String],
                          creatorUuid: Option[String],
                          approverUuid: Option[String],

                          regulationPackages: Option[Seq[RegulationPackagesModel]],
                          regulation_Evaluations: Option[Seq[Regulation_EvaluationModel]]
                        ) {
  def toModel: RegulationModel = {
    new RegulationModel(
      regulationId = this.regulationId,
      name = this.name,

          [.... some other attributes....]

      // Non Database fields
      priceCategory = None,
      slaLevel = None,
      markets = None,
      tags = None,
      crawler = None,
      commentCreatedAt = None,
      creatorComment = None,
      approved = None,
      approverComment = None,
      approvedAt = None,
      creatorUuid = None,
      approverUuid = None,
      regulationPackages = None,
      regulation_Evaluations = None
    )
  }
}

object RegulationApi {
  implicit val extendedRegulation_format: OFormat[RegulationApi] = Jsonx.formatCaseClass[RegulationApi]

  def fromModel(other: RegulationModel): RegulationApi = {
    RegulationApi(
      regulationId = other.regulationId,
      name = other.name,
      
          [.... some other attributes....]

      
      // Non Database fields
      priceCategory = None,
      slaLevel = None,
      markets = None,
      tags = None,
      crawler = None,
      commentCreatedAt = None,
      creatorComment = None,
      approved = None,
      approverComment = None,
      approvedAt = None,
      creatorUuid = None,
      approverUuid = None,
      regulationPackages = None,
      regulation_Evaluations = None
    )
  }
}


/**
  * Case Classes for Return types
  */

case class PmsFindingsWithTags(pmsFinding: RegulationModel, tags: Seq[TagsModel])

object PmsFindingsWithTags {
  implicit val pmsFindingsWithTags: OFormat[PmsFindingsWithTags] = Json.format[PmsFindingsWithTags]
}

case class PmsFindingsWithMarkets(pmsFinding: RegulationModel, markets: Seq[MarketsModel])

object PmsFindingsWithMarkets {
  implicit val pmsFindingsWithMarkets: OFormat[PmsFindingsWithMarkets] = Json.format[PmsFindingsWithMarkets]
}

case class PmsFindingsWithUrls(pmsFinding: RegulationModel, urls: Seq[CrawlerUrlsModel])

object PmsFindingsWithUrls {
  implicit val pmsFindingsWithMarkets: OFormat[PmsFindingsWithUrls] = Json.format[PmsFindingsWithUrls]
}

case class RegulationWithCrawler(regulation: RegulationModel, latestCrawlerResults: Seq[ResultsCrawlerModel], userUuid: Option[String])

object RegulationWithCrawler {
  implicit val regulationWithCrawlers: OFormat[RegulationWithCrawler] = Json.format[RegulationWithCrawler]
}

/**
  * Trait
  */

trait PmsFindingComponent {
  self: HasDatabaseConfigProvider[JdbcProfile] =>

  import profile.api._

  class Regulation(tag: Tag) extends Table[RegulationModel](tag, "Regulation") {
    def regulationId: Rep[Int] = column[Int]("regulationId", O.PrimaryKey, O.AutoInc)

    def name: Rep[String] = column[String]("name")

    def description: Rep[Option[String]] = column[Option[String]]("description")

          [.... some other attributes....]


    def shortDescriptionEn: Rep[Option[String]] = column[Option[String]]("shortDescriptionEn")

    def analysisEn: Rep[Option[String]] = column[Option[String]]("analysisEn")

    // HList-based wide case class mapping
    def * = (
      regulationId ::       name::
      description ::
      
      [.... some other attributes....]
      
      shortDescriptionEn::
      nameEn ::
      descriptionEn ::
      analysisEn :: HNil
      ).mappedWith(Generic[RegulationModel])
  }

  val regulation_query: TableQuery[Regulation] = TableQuery[Regulation] // Query object
}

但我收到以下错误:

更新

【问题讨论】:

  • 您可以手动编写映射器,而无需使用自动生成的案例类的应用/取消应用方法,该方法不会为 >22 个字段案例类生成:)
  • 你能给我举个例子吗?
  • 我不使用自动生成的东西
  • 我的意思是“限制”是 Scala 编译器不会为超过 22 个字段的案例类生成应用/取消应用方法的限制,并且您不能依赖辅助函数 <> in使用这些方法的 Slick。但与往常一样,您可以手动编写最终映射。您可以在此答案中查看示例stackoverflow.com/a/49659436/14044371
  • 我在上面添加了我收到的错误消息的代码。你可以看看吗?提前致谢

标签: scala slick


【解决方案1】:

这个想法是使用一个 HList 来表示一个超过 22 列的表。

您不需要为此使用 slickless/shapeless,如果您不想这样做,也不必使用 codegen,因为内置的 Slick HList 与 mapTo 宏一起使用。

步骤如下:

  1. 添加 HList 导入(并删除光滑/无形的):

    import slick.collection.heterogeneous.{HList, HCons, HNil}
    import slick.collection.heterogeneous.syntax._
    
  2. 将您的* 投影定义为:

    def * = (regulationId :: name :: etc... :: HNil).mapTo[RegulationModel]
    

现在 Slick 网站上有一个食谱部分来说明这一点:https://scala-slick.org/doc/3.3.3/cookbook.html#mapping-more-than-22-fields

如果您想了解有关此 22 位限制的更多详细信息,请在此处发布更长的帖子:https://underscore.io/blog/posts/2016/10/11/twenty-two.html

【讨论】:

  • 我已经更新了我的问题,因为我还有问题。
  • 看起来问题中的代码示例仍在使用mappedWith
  • 我找到了解决方案。问题是模型中的我妈妈数据库字段
  • 警告。当 HList 变得“大”时,编译时间会迅速增加。我在一个有 30-40 列的表上尝试了这个,它编译了五天并没有完成。
猜你喜欢
  • 2013-08-05
  • 2022-10-04
  • 1970-01-01
  • 1970-01-01
  • 2014-09-03
  • 1970-01-01
  • 1970-01-01
  • 2018-11-04
  • 1970-01-01
相关资源
最近更新 更多