Scala Anorm 零到多的正确方法
Scala Anorm zero to many the right way
我有一个由 2 个表组成的简单数据库 - movie
和 comment
,其中评论与电影相关,然后我有以下一段 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
变量有助于重构。)
我有一个由 2 个表组成的简单数据库 - movie
和 comment
,其中评论与电影相关,然后我有以下一段 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
变量有助于重构。)