本文介绍了使用 Anorm RowParser的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

限时删除!!

我已经使用 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 JOINs. 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的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

1403页,肝出来的..

09-06 21:55