使用Anorm RowParser

时间:2014-06-24 10:22:53

标签: scala anorm

我一直在使用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框架性能?

2 个答案:

答案 0 :(得分:11)

解析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,您需要使用多个JOIN来解析结果。我们不是拥有一个大的解析器,而是为它的伴随对象中的每个类构造一个:

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]。然后考虑该更改就像将Address.parser解析器中的User更改为(Address.parser ?)一样简单。

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

答案 1 :(得分:3)

anorm.SqlParser还提供了可信的解析器函数,如.str.int.float.double,...而不是.get[String],{{ 1}},.get[Int].get[Float]。最好的问候。