简体   繁体   中英

Play Scala Anorm One to Many relationship

Coming from play anorm, create a model from json without passing anorm PK value in the json I'm trying to add Seq[Address] to case class like

case class User(
  id: Pk[Long] = NotAssigned,
  name: String = "",
  email: String = "",
  addresses: Seq[Address])

Address is a simple object/class with three Strings. An user can have more than 1 address, how do I get all the addresses along with the User in findAll.

  def findAll(): Seq[User] = {
    Logger.info("select * from pt_users")
    DB.withConnection { implicit connection =>
      SQL(
        """
          select * from pt_users where name like {query} limit {size} offset {offset}   
        """).as(User.list *)
    }
  }

A side note about something I have found useful: if you're not sure you will always want to fetch the addresses for a user, you can avoid adding that relation as a field and instead use tuples or other data structures for representing them. This would allow you to have a method like this:

def allUsersWithAddresses(): Map[User, Seq[Address])] = ...

But still have methods that return only users without having the joined data.

To read a join (or subselect) you will have to parse the combined output with a parser, something like this:

.as(User ~ Address *).groupBy(_._1)

If you really want to put the addresses inside of user, you'd have to make the address list empty from the user parser and then map each distinct user into one with the addresses:

.as(User ~ Address *).groupBy(_._1).map { 
  case (user, addresses) => user.copy(addresses = addresses)
}

Note, the examples are just pointers to an approximate solution, not copy-paste-and-compile ready code.

Hope it helped!

This will work

/** Parses a `Blog` paired with an optional `Post` that can be later be collapsed into one object. */
val parser: RowParser[(Blog, Option[Post])] = {
    simple ~ Post.parser.? map {
        case blog~post => (blog, post)
    }
}


def list: List[Blog] = {
    DB.withConnection { implicit c =>
        SQL("""
            SELECT * FROM blogs b
            LEFT OUTER JOIN posts p ON(p.blog_id = b.id)
        """).as(parser *)
            .groupBy(_._1)
            .mapValues(_.map(_._2).flatten)
            .toList
            .map{ case (blog, posts) => blog.copy(posts = posts) }
    }
}

Copied from https://index.scala-lang.org/mhzajac/anorm-relational/anorm-relational/0.3.0?target=_2.12

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM