3

我正在尝试构建一个类似于“计算机”示例中的列表页面。我的环境是 Play 2.0 和 PostrgreSQL 9.0

我的用户对象中有以下方法:

 def list(page: Int = 0, pageSize: Int = 10, orderBy: Int = 1, filter: String = "%"): Page[User] = {
    val offset = pageSize * page
    val mode = if (orderBy > 0) "ASC NULLS FIRST" else "DESC NULLS LAST"

    Logger.debug("Users.list with params: page[%d] pageSize[%d] orderBy[%d] filter[%s] order[%s]".format(page, pageSize, orderBy, filter, mode))

    DB.withConnection {
      implicit connection =>

        val users = SQL(
          """
            select * from publisher
            where name ilike {filter}
            order by {orderBy} %s
            limit {pageSize} offset {offset}
          """.format(mode)
        ).on(
          'pageSize -> pageSize,
          'offset -> offset,
          'filter -> filter,
          'orderBy -> scala.math.abs(orderBy)
        ).as(User.simple *)

        val totalRows = SQL(
          """
            select count(*) from publisher
            where name like {filter}
          """
        ).on(
          'filter -> filter
        ).as(scalar[Long].single)

        Page(users, page, offset, totalRows)
    }

  }

我提供的“orderBy”的值无关紧要,订单始终基于实体的 ID。

Anorm 生成的查询是有效的 PostgreSQL,并且在直接针对数据库运行时可以正常工作。但似乎 Anorm 解析器忽略了返回结果的顺序,而是返回一个按“id”排序的列表。

我什至尝试将查询简化为 a "select * from publisher order by 2 ASC/DESC",但没有任何问题是固定的,Anorm 在返回时忽略了排序。

关于如何解决这个问题的任何建议?

4

1 回答 1

4

感谢 Play 邮件列表中的 Guillaume,我找到了一种解决方法。

除按顺序排列的占位符外,所有占位符都有效。更糟糕的是,当您跟踪日志时,驱动程序会生成正确的查询,而 PostgreSQL 正在接收它。我不确定这是怎么回事,非常令人困惑,但如果我删除那个占位符,它就可以工作。

沉闷 :(

我是这样解决的:

val users = SQL(
  """
    select * from publisher
    where name ilike {filter}
    order by %d %s
    limit {pageSize} offset {offset}
  """.format(scala.math.abs(orderBy), mode)
).on(
  'pageSize -> pageSize,
  'offset -> offset,
  'filter -> filter
).as(User.simple *)

现在你会尖叫“SQL INJECTION”。放松。尽管可能以某种方式可能,但它orderBy是一个整数(为了更安全,我们将其转换为 abs 值)。如果您尝试调用提供orderBy字符串的控制器,Play 将返回404错误。所以只允许整数。如果没有对应于给定整数的列,order by则忽略。所以,不理想,但还不错。

于 2012-03-20T21:23:05.450 回答