-->

How to better parse the same table twice with Anor

2019-04-23 07:39发布

问题:

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 RowParsers 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.