问题描述
我已经使用 Play 框架 2.0 大约 6 个月了,我一直想知道为什么他们使用这么多样板代码来解析我的 SQL 查询返回,如下所示:
I have been using Play framework 2.0 for about 6 months, I have been wondering why they use so many boilerplate code to parse from my SQL query returns, like below:
case class Journal_accountDetail(amount: Double, states: Boolean)
val Journal_AccountParser: RowParser[Journal_accountDetail] = {
get[Double] ("amount") ~
get[Boolean] ("states") map({
case amount~states => Journal_accountDetail(amount,states)
})
}
是否可以提高 Play 框架的性能??
Is it something that boost Play framework performance ??
推荐答案
解析 API 起初看起来有点乏味,但是当您开始组合和重用解析器时,它会非常强大,并且很多 比每个返回 SQL 结果的函数中的模式匹配更丑.
The parsing API can seem a bit tedious at first, but it's quite powerful when you start combining and re-using the parsers, and much less ugly than pattern matching in every function that returns an SQL result.
想象一下这样的事情:
case class User(id: Int, name: String, address: Address)
case class Address(id: Int, street: String, city: String, state: State, country: Country)
case class State(id: Int, abbrev: String, name: String)
case class Country(id: Int, code: String, name: String)
要构造User
,您需要使用多个JOIN
来解析结果.我们没有一个大型解析器,而是为它的伴生对象中的每个类构造一个:
To construct the User
you need to parse a result with multiple JOIN
s. Rather than having one large parser, we construct one for each class in it's companion object:
object User {
val parser: RowParser[User] = {
get[Int]("users.id") ~
get[String]("users.name") ~
Address.parser map {
case id~name~address => User(id, name, address)
}
}
}
object Address {
val parser: RowParser[Address] = {
get[Int]("address.id") ~
get[String]("address.street) ~
get[String]("address.city") ~
State.parser ~
Country.parser map {
case id~street~city~state~country => Address(id, street, city, state, country)
}
}
}
object State {
val parser: RowParser[State] = {
get[Int]("states.id") ~
get[String]("states.abbrev") ~
get[String]("states.name") map {
case id~abbrev~name => State(id, abbrev, name)
}
}
}
object Country {
val parser: RowParser[Country] = {
get[Int]("countries.id") ~
get[String]("countries.code") ~
get[String]("countries.name") map {
case id~code~name => Country(id, code, name)
}
}
}
注意我如何在解析器中使用完整的表空间,以避免列名冲突.
总而言之,这看起来像很多代码,但对于每个源文件来说,它只占用很小的空间.最大的好处是我们的 User
解析器非常干净,尽管它结构复杂.假设在 User
中,address
实际上是 Option[Address]
.然后解释这种变化就像将 User
解析器中的 Address.parser
更改为 (Address.parser ?)
一样简单.
Altogether, this looks like a lot of code, but for each source file it's only a small footprint. And the largest benefit is that our User
parser is quite clean despite it's complex structure. Let's say in User
the address
is actually Option[Address]
. Then accounting for that change is as simple as changing Address.parser
in the User
parser to (Address.parser ?)
.
对于解析简单的查询,是的,它看起来确实像很多样板.但在解析上述示例(以及更复杂的示例)时,我非常感谢解析 API.
For parsing simple queries, yes it does seem like a lot of boilerplate. But I'm quite thankful for the parsing API when it comes to parsing examples like the one above (and much more complex ones).
这篇关于使用 Anorm RowParser的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!