Suppose I have the following two classes:
case class User(id: Long, name: String)
case class Message(id: Long, body: String, to: User, from: User)
The RowParser
s might look something like this:
val parser: RowParser[User] = {
get[Long]("users.id") ~ get[String]("users.name") map {
case id~name => User(id, name)
}
}
val parser: RowParser[Message] = {
get[Long]("messages.id") ~
get[String]("messages.name") ~
User.parser ~
User.parser map {
case id~body~to~from => Message(id, body, to, from)
}
}
Except that this won't work, because when joining the users
table twice, Anorm will only parse the first joined columns (twice), so that to
and from
will be the same.
This can be overcome using column aliases in the User
parser:
def parser(alias: String): RowParser[User] = {
getAliased[Long](alias + "_id") ~ getAliased[String](alias + "_name") map {
case id~name => User(id, name)
}
}
Then using different aliases for each User
in the Message
parser:
val parser: RowParser[Message] = {
get[Long]("messages.id") ~
get[String]("messages.name") ~
User.parser("to") ~
User.parser("from") map {
case id~body~to~from => Message(id, body, to, from)
}
}
This is okay for simple scenarios, but what if User
is more complicated and has an Address
with a State
and Country
, etc? That would require aliasing multiple tables and parsers, which gets quite messy.
Is there a better way to accomplish this? That is, I'm looking to select all of the relevant data in one query, and parse it using parser combinators, without a massive column aliasing scheme.
来源:https://stackoverflow.com/questions/27652731/how-to-better-parse-the-same-table-twice-with-anorm