【问题标题】:Using Anorm RowParser使用异常行解析器
【发布时间】:2014-06-24 10:22:52
【问题描述】:

我已经使用 Play framework 2.0 大约 6 个月了,我一直想知道为什么他们使用这么多样板代码来解析我的 SQL 查询返回,如下所示:

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 框架的性能吗??

【问题讨论】:

  • 你能举一个使用较少样板的库/框架的例子吗?
  • 如果我没记错的话,Ruby on rails / yii 不会使用类似的代码来获取或使用 SQL 查询结果。对吧?我还是个新手..
  • 一句话,为了类型安全。

标签: scala anorm


【解决方案1】:

解析 API 一开始可能看起来有点乏味,但当您开始组合和重用解析器时,它会非常强大,并且比每个返回 SQL 的函数中的模式匹配更丑结果。

想象一下这样的事情:

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,您需要解析具有多个JOINs 的结果。我们没有一个大型解析器,而是为它的伴生对象中的每个类构造一个:

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 解析器非常干净,尽管它的结构很复杂。假设在Useraddress 实际上是Option[Address]。然后考虑该更改就像将 User 解析器中的 Address.parser 更改为 (Address.parser ?) 一样简单。

对于解析简单的查询,是的,它确实看起来像很多样板文件。但是在解析上述示例(以及更复杂的示例)时,我非常感谢解析 API。

【讨论】:

  • 谢谢你的把戏。但是,我更关心性能。这只是为了更好的代码可读性吗?我在 Play 2.0 中读过一次关于 JSON 解析的文章,也有一些样板代码,但有人说它可以帮助在执行过程中更快地生成 Json..
  • 性能上确实不应该有任何明显的差异。类型安全和可读性应该是第一位的。过早的优化不是要走的路。您的 SQL 查询比解析器更可能导致性能问题。我已经使用 Play 一年多了,没有遇到由解析器引起的性能问题。
  • 这很棒(我认为)。你能举一个异常查询的例子吗?
【解决方案2】:

anorm.SqlParser 还提供了方便的解析器函数,例如.str.int.float.double、...而不是.get[String].get[Int].get[Float].get[Double]。最好的问候。

【讨论】:

    猜你喜欢
    • 2012-10-19
    • 1970-01-01
    • 1970-01-01
    • 2021-11-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多