我正在尝试动态地将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>>]
有没有人知道更好的解决方案或我出错的地方?
答案 0 :(得分:0)
我解决这个问题的方法是更改我的sortMap
以包含隐式列类型的表格类型(从Map[String, Rep[_]]
到Map[String, ATable => 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
。我正在考虑将这些地图包含在表格代码生成脚本中。
答案 1 :(得分:0)
你只需要包含像
这样的代数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);
}
}