我需要在*
中的MySQL
数据库中读取某些枚举值(除了其他常规内容,包括一些可选的空值) 。我使用Scala
查询ScalikeJdbc
并解析结果集。我在it's docs中找不到解析枚举类型的任何提及(也许我需要深入挖掘)。
但是我的目标应用程序需要有两种加载数据的方式:数据库和MySQL
文件。因此,我还使用ScalaJson
(JSON
)来解析Json文件,以便读取与Play Framework
数据库完全相同的数据。
我知道MySQL
和ScalikeJdbc
都支持使用ScalaJson
的案例类 es来解析数据>自动转换。
我的问题是:
Scala
是否支持解析枚举值 like ScalaJson
?ScalikeJdbc
来解析case class
和ScalikeJdbc
中的数据,还是需要将它们区分开来?我的ScalaJson
将包含自定义类型的参数,而自定义类型的参数又是case class
。除了枚举值之外,这些case class
接受以下类型的参数(基本上,它们不包含完全相同类型的参数,但级别的复杂性会完全相同):
case class
,Int
String
,Option[Int]
Option[String]
Option[Seq[ (Int, String, Option[Int], Option[String]) ]]
/ JSON
文件中读取数据时)或开销添加枚举太多了,无法证明其好处?答案 0 :(得分:0)
正如在对此问题的评论中所说,我直接从Enums
数据库或MySQL
阅读了JSON
。显然,这些字段现在在数据库中是简单的VARCHAR
,我将验证逻辑移到我的Scala
代码中。由于我正在单独执行验证,因此我用来保存从case class
或MySQL
读取的数据的JSON
不再具有任何Enum.Value
类型字段。
我想说在数据库中直接使用Enums
会更有意义;但由于缺乏简单的解决方案,我选择了这种解决方法。这仍然是一个悬而未决的问题,一旦找到解决方案,我将更新答案。
来到我的问题的另一部分
可以使用相同的case类来解析ScalikeJdbc中的数据 和ScalaJson还是他们需要不同?
是强>
我使用case class
创建了companion object
es,我可以在ScalikeJdbc
以及{{1}中将它们用于自动转换 }}。我发布了一个完整的ScalaJson
及其case class
,用于此双重用途。
注意:此代码示例来自框架,旨在将 companion 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)
的{{1}}
object
此方法查询case class
数据库正在使用def getTables(db: Db)
MySQL
ScalikeJdbc
这些是implicit val dateTimeJsReader = JodaReads.jodaDateReads("yyyyMMddHHmmss")
implicit val dateTimeJsReader = JodaReads.jodaDateReads("yyyyMMddHHmmss")
读写转换器(由Joda
用于)DateTime
ScalaJson
参数{ {1}}
Joda
DateTime
这些是给定case class
的读写转换器
最后,这是用于从Json文件
读取此案例类数据的代码片段implicit val reads = Json.reads[Table]
像我这样的 noobs 的最后一条建议:除非您对implicit val writes = Json.writes[Table]
(以及case class
解析,一般而言)感到满意,否则请避免使用{{1} }方法(上面的代码段使用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
}
方法)以克服像this这样的细微错误。
修改-1 强>
ScalikeJdbc是否支持解析像ScalaJson这样的枚举值?
获取ScalaJson
与JSON
无关:如果您有Json.parse(jsonString).asOpt[T]
,转换为.as[T]
有多难?
这是一个小例子:
Enum.Value
很难理解为什么在我面前就看不到答案:(ScalikeJdbc
方法)
..总的来说,根本不使用Enums是个好主意。
是的,绝对
拥有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
比使用Scala
要好得多。