0

需要从. _ _ MySQL_ ScalaScalikeJdbc用于查询MySQL和解析结果集。我在它的文档中找不到任何关于解析枚举类型的内容(也许我需要更深入地挖掘)。

但是我的目标应用程序需要有两种加载数据的方式:数据库和JSON文件。因此,我还使用ScalaJson( ) 来解析 Json 文件,以读取与从数据库Play Framework中读取完全相同的数据。MySQL

我知道两者都ScalikeJdbc支持通过使用case class es 进行自动转换ScalaJson解析数据。Scala


我的问题是:

  • 是否ScalikeJdbc支持解析枚举 ScalaJson
  • 是否可以使用相同的case class方法来解析两者中的数据ScalikeJdbcScalaJson或者它们是否需要不同?我case class的问题将包含自定义类型的参数,而这些参数case class本身就是 es。case class除了Enum 值之外,这些es 还接受以下类型的参数(基本上,它们不包含完全相同类型的参数,但复杂程度是相同的):
    • Int,String
    • Option[Int],Option[String]
    • Option[Seq[ (Int, String, Option[Int], Option[String]) ]]
  • 通过添加额外的手动验证可以完全取消枚举,尽管最终结果可能不那么整洁。也就是说,一般来说,使用枚举JSON是一个好主意(特别是在从数据库或/XML文件读取数据时)还是添加枚举的开销太大而无法证明它们的好处?
4

1 回答 1

0

正如对该问题的评论所述,我取消了Enums直接从MySQL数据库或JSON. 显然,这些字段现在VARCHAR是数据库中的 simple ,我将验证逻辑移到了我的Scala代码中。由于我单独执行验证,因此case class我用来保存从读取的数据MySQLJSON不再具有任何Enum.Value类型字段的 es。

Enums我会说直接在数据库中会更有意义。但由于缺乏简单的解决方案,我选择了这种解决方法。这仍然是一个悬而未决的问题,一旦找到解决方案,我将更新答案。


来到我问题的另一部分

可以使用相同的案例类来解析 ScalikeJdbc 和 ScalaJson 中的数据,还是它们需要不同?

是的

我用 s 创建了case classes,我可以在 .s 和 .s中companion object使用它们进行自动转换。我正在发布一个完整的以及它的服务这个双重目的ScalikeJdbcScalaJsoncase classcompanion object

注意:此代码示例来自一个旨在表格从一个位置移动到另一个位置的框架。[实际生产代码] MySQL

案例类:

case class Table(dbId: Option[Int] = None,
                 id: Option[Int] = None,
                 name: String,
                 shouldCopy: Option[Boolean] = None,
                 lastUpdated: Option[DateTime] = None
                )

伴侣对象:

object Table {

  private def mapResultToTable(rs: WrappedResultSet): Table = Table(
    dbId = rs.intOpt("db_id"),
    id = rs.intOpt("id"),
    name = rs.string("name"),
    shouldCopy = rs.booleanOpt("should_copy"),
    lastUpdated = rs.dateTimeOpt("last_updated").flatMap { zonedDateTime: ZonedDateTime =>
      Some(DateTime.parse(zonedDateTime.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME)).plusMinutes(330))
    }
  )

  def getTables(db: Db)(implicit session: DBSession): Seq[Table] = {
    sql"""
       SELECT
         *
       FROM
         db_name.tables
       WHERE
         db_id = ${db.id} AND
         should_copy = b'1'
       ORDER BY
         name ASC
    """.
      map(mapResultToTable).
      list().
      apply()
  }

  // for Play-Json [Scala-Json]
  implicit val dateTimeJsReader = JodaReads.jodaDateReads("yyyyMMddHHmmss")
  implicit val dateTimeWriter = JodaWrites.jodaDateWrites("dd/MM/yyyy HH:mm:ss")

  implicit val reads = Json.reads[Table]
  implicit val writes = Json.writes[Table]
}

以下是对代码特定部分的解释:

  • def mapResultToTable(rs: WrappedResultSet)

    此方法读取数据库查询的结果并构建一个objectcase class

  • def getTables(db: Db)

    此方法查询MySQL数据库正在使用ScalikeJdbc

  • implicit val dateTimeJsReader = JodaReads.jodaDateReads("yyyyMMddHHmmss")

  • implicit val dateTimeJsReader = JodaReads.jodaDateReads("yyyyMMddHHmmss")

    这些是用于参数的Joda DateTime 读写转换器(由 使用ScalaJsonJoda DateTimecase class

  • implicit val reads = Json.reads[Table]

  • implicit val writes = Json.writes[Table]

    这些是给定的读写转换器case class


最后,这是从 Json 文件中读取此案例类数据的代码片段

val tableOpt: Option[Table] = try {
  val rawJsonString: String = Source.fromFile("path/to/file/fileName.json").mkString
  Some(Json.parse(rawJsonString).as[Table])
} catch {
  case ex: Throwable =>
    println(s"Exception while reading Json file: '$ex'")
    None
}

对像我这样的菜鸟的最后一条建议:除非您对ScalaJson(并且JSON通常会解析)感到满意,否则请避免使用Json.parse(jsonString).asOpt[T]方法(上面的代码片段使用.as[T]方法)以克服像这样的细微错误。


编辑-1

ScalikeJdbc 是否支持解析像 ScalaJson 这样的枚举值?

获得Enum.Value真的无关ScalikeJdbc:一旦你拥有了String,转换成有多难Enum.Value

这是一个小例子:

// Enum
object CloudProvider extends Enumeration {

  val AWS: Value = Value("aws")
  val MicrosoftAzure: Value = Value("microsoft-azure")
  val GoogleCloud: Value = Value("google-cloud")
}

// Case Class
case class SiteInfo(website: String, provider: CloudProvider.Value)

// Mapper method
def mapResult(rs: WrappedResultSet): SiteInfo = {
  val website: String = rs.string("website")
  val provider: CloudProvider.Value = CloudProvider.values.
    find(_.toString == rs.string("provider")).
    getOrElse(CloudProvider.AWS)

  SiteInfo(website, provider)
}

很难理解为什么当它就在我面前时我看不到答案:(mapResult方法)


..一般来说,使用枚举是个好主意吗..

是的,一点没错

拥有Enum类型的全部意义在于限制变量可以取值的范围。除了Enum.

同样,一旦您对使用的语言/库有足够的了解(当时我不太了解ScalaScalikeJdbc,使用绝对没有开销(从编码的角度来看)Enum;事实上,它们使代码更加清晰。不用说,即使从性能的角度来看,使用Enums 也比 using 好得多String

于 2018-02-22T15:45:38.993 回答