【问题标题】:Mapped Tables Column Type Conversion on Apply UnApply映射表列类型转换应用 UnApply
【发布时间】:2021-07-15 09:44:06
【问题描述】:

我有一个具有字段 filter 的类 ReportTemplate。现在 ReportTemplateRow 是代表 ReportTemplate 的 db 类。我想要的是在 ReportTemplate 中有 JsonAST.JValue 类型的过滤器,但在 ReportTemplateRow 中有 String 类型(当保存在 db 上时)......我希望 ReportTemplate 和 ReportTemplateRow 之间的转换自动发生。

下面的代码可以正常工作,但显然没有任何转换...所以每次我需要在我的代码中使用 ReportTemplate 时,我都必须将 ReportTemplate 显式转换为 ReportTemplateResponse...

我知道我应该覆盖 apply 和 unapply 方法,但我无法弄清楚具体如何...我用不同的关键字搜索了这个问题,但找不到确凿的答案。

case class ReportTemplate(id: Long, reportId: Long, name: String, group : Option[String], filter : String, created : DateTime)

class ReportTemplateRow(tag: Tag) extends Table[ReportTemplate](tag, "ReportTemplate"){
  def id = column[Long]("id", O.PrimaryKey, O.AutoInc)
  def reportId = column[Long]("reportId")
  def name = column[String]("name")
  def group = column[Option[String]]("group")
  def filter = column[String]("filter", O.SqlType("text"))
  def created = column[DateTime]("created",O.SqlType("timestamp not null default CURRENT_TIMESTAMP"))

  def * = (id, reportId, name, group, filter, created) <> (ReportTemplate.tupled, ReportTemplate.unapply)

我期望拥有类似于以下内容的内容:

case class ReportTemplate(id: Long, reportId: Long, name: String, group : Option[String], filter : JsonAST.JValue, created : DateTime)
object ReportTemplate {
  def unapply(r: ReportTemplate) : (Long, Long, String, Option[String], String, DateTime) = (r.id, r.name, r.group, JsonAST.compactRender(r.filter), r.created)
  def apply(id: Long, reportId: Long, name: String, group : Option[String], filter : String, created : DateTime) : ReportTemplate =
    ReportTemplate(id, reportId, name, group, parse(filter), created)
}

class ReportTemplateRow(tag: Tag) extends Table[ReportTemplate](tag, "ReportTemplate"){
  def id = column[Long]("id", O.PrimaryKey, O.AutoInc)
  def reportId = column[Long]("reportId")
  def name = column[String]("name")
  def group = column[Option[String]]("group")
  def filter = column[String]("filter", O.SqlType("text"))
  def created = column[DateTime]("created",O.SqlType("timestamp not null default CURRENT_TIMESTAMP"))

  def * = (id, reportId, name, group, filter, created) <> (ReportTemplate.apply, ReportTemplate.unapply)

【问题讨论】:

    标签: scala slick


    【解决方案1】:

    据我了解您的问题,您有一个文本数据库列 (filter),您希望在 Scala 中以不同类型使用它。

    Slick 为此提供了一个基于列的机制MappedColumnType.base

    这个想法是:

    • 在您的数据库行类中,您可以根据需要键入列(在本例中为 JSON)。
    • 您还提供了从该类型 (JSON) 到数据库类型 (String) 的隐式转换。

    详细信息在the manual 和Essential Slick 教程chapter 5 中。

    概括地说,对于你的情况,它可能是这样的(nb:不会编译;只是一个草图):

    implicit val filterTypeMapping =
        MappedColumnType.base[Json, String](
          json => json.toString, // or however you do this for the JSON you're using
          txt  => json.parse(txt).get /// or however you do this in the JSON lib you're using
        )
    

    在此范围内,Slick 将“学习”如何将您的 JSON 数据类型转换为对数据库友好的类型。

    请注意,您将文本解析为 JSON 可能会失败。这可能是一个运行时错误,或者您可以选择将其表示为不同的类型,例如 Try[Json] 或类似的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-02-16
      • 2021-10-30
      • 1970-01-01
      • 2018-09-15
      • 2017-11-18
      • 2018-07-10
      • 2011-10-23
      相关资源
      最近更新 更多