【问题标题】:Dynamic sortBy with Slick 3使用 Slick 3 进行动态排序
【发布时间】:2016-09-13 19:17:14
【问题描述】:

我正在尝试将 sortBy 动态包含到我的查询中,该查询根据查询参数中的字符串名称进行排序。在 Slick 3 中,这已被证明是相当棘手的。目前我的设置是:

trait Model {
    type ATable <: AbstractTable[_]

    def tableQuery: TableQuery[ATable]

    def sortMap: Map[String, Rep[_]]

    private def sortKey[T](e: ATable, sort: (String, SortOrder)): ColumnOrdered[_] = sort match {
       case (field, SortOrder.Asc) => ColumnOrdered(sortMap.getOrElse(field, throw new ClientException(s"Can't sort by $field")), Ordering(Ordering.Asc))
       case (field, SortOrder.Desc) => ColumnOrdered(sortMap.getOrElse(field, throw new ClientException(s"Can't sort by $field")), Ordering(Ordering.Desc))
    }
    def all(sort: (String, SortOrder)) = tableQuery.sortBy(sortKey(_, sort)).result
}

object User extends Model {
    type ATable = Tables.User
    val tableQuery = Tables.User

    val sortMap = Map( "id" -> tableQuery.id )
}

但是运行db.run(User.all(("id", SortOrder.Asc))会抛出以下错误:

slick.SlickException: No type for symbol name found in Vector[t2<@t3<UnassignedType>>]

有谁知道更好的解决方案或我哪里出错了?

【问题讨论】:

    标签: scala orm slick-3.0


    【解决方案1】:

    我解决这个问题的方法是将我的sortMap 更改为包含具有隐式列类型的表类型(从Map[String, Rep[_]]Map[String, ATable =&gt; Rep[_]]):

    trait Model {
        type ATable <: AbstractTable[_]
    
        def tableQuery: TableQuery[ATable]
    
        def sortMap: Map[String, ATable => Rep[_]]
    
        private def sortKey(baseQ: Query[ATable, ATable#TableElementType, Seq], sort: (String, SortOrder)) = {
           val rep = sortMap.getOrElse(sort._1, throw new ClientException(s"Can't sort by ${sort._1}"))
           val orderedRep = sort._2 match {
              case SortOrder.Asc => (t: ATable) => ColumnOrdered(rep(t), slick.ast.Ordering(slick.ast.Ordering.Asc))
              case SortOrder.Desc => (t: ATable) => ColumnOrdered(rep(t), slick.ast.Ordering(slick.ast.Ordering.Desc))
           }
           q.sortBy(orderedRep)
       }
    
       def all(sort: (String, SortOrder)) = sortKey(tableQuery, sort).result
    }
    
    object User extends Model {
        type ATable = Tables.User
        val tableQuery = Tables.User
    
        val sortMap = Map( "id" -> { (t: ATable) => t.id } )
    }
    

    此解决方案的唯一次优方面是,如果将新列添加到数据库中,则必须手动将其添加到 sortKey。我正在考虑将这些地图包含在表格代码生成脚本中。

    【讨论】:

      【解决方案2】:

      你只需要在生成中包含类似

      的东西
      val columns =  Map( "id" -> { (t: User) => t.id } )
      

      并像这样使用它:

      class UserDAO{ 
      //...
      baseQuery = filterContext.sort.foldLeft[Query[User, UserRow, Seq]](User) ((_, s) => UserColumnFilter.getSort(s,User.baseTableRow.columns));
      //...
      }
      
      case class Sort(columnName:String,value: String) {}
      
      case class FilterContext(filters:List[Filter],page:Int,pageSize:Int,sort:List[Sort])
          object UserColumnSort extends ColumnSort[User,UserRow](User)
          class ColumnSort[T<:Table[C],C](query:TableQuery[T]) 
          {      
      
            def getSort(s:Sort,columns:Map[String, T => Rep[_]]):Query[T, C, Seq] =  {
              val aux = columns.getOrElse(s.columnName, throw new Exception(s"Can't sort by ${s.columnName}"));
                val orderedRep = s.value match {
                    case "asc" => (t: T) => ColumnOrdered(aux(t), slick.ast.Ordering(slick.ast.Ordering.Asc))
                    case _ => (t: T) => ColumnOrdered(aux(t), slick.ast.Ordering(slick.ast.Ordering.Desc))
                 }
                 return query.sortBy(orderedRep);
      
            }
          }
      

      【讨论】:

        猜你喜欢
        • 2012-06-27
        • 2016-01-29
        • 1970-01-01
        • 1970-01-01
        • 2014-08-02
        • 2018-01-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多