Scala Anorm 零到多的正确方法

Scala Anorm zero to many the right way

我有一个由 2 个表组成的简单数据库 - moviecomment,其中评论与电影相关,然后我有以下一段 scala 异常代码:

case class Comment(commentId: Long, comment: String)
case class Movie(movieId: Long, name: String, movieType: String)

object MovieDao {
  val movieParser: RowParser[Movie] = {
    long("movieId") ~
    str("name") ~
    str("movieType") map {
      case movieId ~ name ~ movieType => Movie(movieId, name, movieType)
    }
  }

  val commentParser: RowParser[Comment] = {
    long("commentId") ~
    str("comment") map {
      case commentId ~ comment => Comment(commentId, comment)
    }
  }

  def getAll(movieType: String) = DB.withConnection {
    implicit connection =>
      SQL(
        """
          |SELECT
          |movie.movieId,
          |movie.name,
          |movie.movieType,
          |comment.commentId,
          |comment.comment
          |FROM movie
          |LEFT JOIN comment USING(movieId)
          |WHERE movieType = {movieType}
        """.stripMargin)
      .on("movieType" -> movieType)
      .as(((movieParser ~ (commentParser ?)) map (flatten)) *)
      .groupBy(_._1) map {(mc: (Movie, List[(Movie, Option[Comment])])) =>
        mc match {
          case (a, b) => (a, b filter { //filter rows with no comments
            case (c, Some(d)) => true
            case _ => false
          } map(_._2))
        }
      } toList
  }
}

我的目标是 return List[(Movie, Option[List[Comment]])]getAll 方法,所以我可以遍历电影并尽可能简单地检查是否有任何评论,e.i .匹配评论列表中的 None 或 Some。我目前正在 returning List[(Movie, Option[List[Option[Comment]])] 并且我只能检查评论列表的大小(感谢使用 filter 方法),我认为这不是正确的方法在 scala 中做。

我的第二个问题是关于解析查询本身,我认为这只是让我的处理方式变得复杂。有没有更简单更好的解决方案来使用 anorm 解析 0..N 关系?

Peter,它的风格可能比任何截然不同的东西都要多,但是对于 MovieComments 案例 class,你可以这样写:

case class MovieComments(movie: Movie, comments: List[Comment])

  val movieCommentsP =
    movieParser ~ (commentParser ?) map {
      case movie ~ comment =>
        MovieComments(movie,if (comment.isEmpty) List() else List(comment.get))
  }

  val movieSqlSelector = "m.movieId, m.name, m.movieType"
  val commentSqlSelector = "c.commentId, c.comment"

  def getAll(movieType: String) :List[MovieComments]= DB.withConnection {
    implicit connection =>
      (SQL(
        s"""
          |SELECT
          |$movieSqlSelector,
          |$commentSqlSelector
          |FROM movie
          |LEFT JOIN comment USING(movieId)
          |WHERE movieType = {movieType}
        """.stripMargin)
        .on('movieType -> movieType)
        .as(movieCommentsP *)
        .groupBy(_.movie.movieId) map { 
            case (movieId,movieComments) => 
              MovieComments(
                  movieComments.head.movie,
                  movieComments.flatMap(_.comments))
        }
      ).toList
  }

您可能真的需要 Option[List[Comment]],但 List[Comment] 不行吗? List() 毕竟是 "no comment" 的情况。 (P.S。我发现使用 sqlSelector 变量有助于重构。)