Scala slick动态比较运算符
我正在用scala和slick开发一个restful web服务。我正在尝试实现过滤。我唯一无法工作的是动态设置比较操作的运算符。我想支持==,=!=,=就像 我在使用泛型的Scala slick动态比较运算符,scala,slick,slick-3.0,Scala,Slick,Slick 3.0,我正在用scala和slick开发一个restful web服务。我正在尝试实现过滤。我唯一无法工作的是动态设置比较操作的运算符。我想支持==,=!=,=就像 我在使用泛型的filteringOperator函数中遇到问题,但找不到它。例外情况如下: value === is not a member of HardwareRepo.this.dbConfig.driver.api.Rep[A] 有人有主意吗 def filtering(exp: FilterExpression): (H
filteringOperator
函数中遇到问题,但找不到它。例外情况如下:
value === is not a member of HardwareRepo.this.dbConfig.driver.api.Rep[A]
有人有主意吗
def filtering(exp: FilterExpression): (HardwareTable) => Rep[Option[Boolean]] = {
exp.field match {
case "serialNumber" => filteringOperator(exp, _.serialNumber, exp.value)
case "online" => filteringOperator(exp, _.online, Try(exp.value.toBoolean).getOrElse(false))
case _ => throw new FilterFieldNotSupportedException(s"Filter field '${exp.field}' not supported")
}
}
def filteringOperator[A](exp: FilterExpression, x: Rep[A], y: A): Rep[Option[Boolean]] = {
exp.operator match {
case FilterExpressionOperator.Equals => x === y
...
}
}
def all(offset: Int, size: Int, filter: List[FilterExpression]): Future[List[Hardware]] = {
var q = Hardwares.to[List]
//filtering
for (exp <- filter) {
try {
q = q.filter(filtering(exp))
} catch {
case ex: FilterFieldNotSupportedException => return Future.failed(ex)
}
}
//pagination
db.run(q.drop(offset).take(size).result)
}
def筛选(exp:filtereexpression):(硬件表)=>Rep[选项[布尔]]{
经验场匹配{
案例“serialNumber”=>filteringOperator(exp、\u0.serialNumber、exp.value)
case“online”=>filteringOperator(exp,u.online,Try(exp.value.toBoolean.getOrElse(false))
case=>抛出新的FilterFieldNotSupportedException(不支持s“筛选器字段${exp.field}”)
}
}
def filteringOperator[A](exp:FilterExpression,x:Rep[A],y:A):Rep[Option[Boolean]={
经验运算符匹配{
case FilterExpressionOperator.Equals=>x==y
...
}
}
def all(偏移量:Int,大小:Int,过滤器:列表[FilterExpression]):Future[List[Hardware]={
var q=硬件。到[列表]
//过滤
for(exp返回Future.failed(ex)
}
}
//分页
db.run(q.drop(偏移量)、take(大小)、result)
}
整个源代码:
package models
import java.sql.Timestamp
import java.util.UUID
import javax.inject.Inject
import helper.{FilterExpression, FilterExpressionOperator, SortExpression, SortExpressionOrder}
import play.api.db.slick.DatabaseConfigProvider
import helper.exceptions.{EntityAlreadyExistsException, FilterFieldNotSupportedException, SortFieldNotSupportedException}
import slick.driver.JdbcProfile
import slick.lifted.ColumnOrdered
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
import scala.util.Try
case class Hardware(id: UUID,
createdAt: Timestamp,
serialNumber: String,
color: Int,
online: Boolean,
renterCount: Int)
class HardwareRepo @Inject()()(protected val dbConfigProvider: DatabaseConfigProvider) {
val dbConfig = dbConfigProvider.get[JdbcProfile]
val db = dbConfig.db
import dbConfig.driver.api._
private val Hardwares = TableQuery[HardwareTable]
val allowedSorting = Map( "id" -> { (hw: Hardware) => hw.id } )
private def _findById(id: UUID): DBIO[Option[Hardware]] =
Hardwares.filter(_.id === id).result.headOption
private def _findBySerialNumber(serialNumber: String): Query[HardwareTable, Hardware, List] =
Hardwares.filter(_.serialNumber === serialNumber).to[List]
def findById(id: UUID): Future[Option[Hardware]] =
db.run(_findById(id))
def findBySerialNumber(serialNumber: String): Future[List[Hardware]] =
db.run(_findBySerialNumber(serialNumber).result)
def sorting(exp: SortExpression): (HardwareTable) => ColumnOrdered[_] = {
exp.field match {
case "id" => if (exp.order == SortExpressionOrder.Asc) _.id.asc else _.id.desc
case "serialNumber" => if (exp.order == SortExpressionOrder.Asc) _.serialNumber.asc else _.serialNumber.desc
case "createdAt" => if (exp.order == SortExpressionOrder.Asc) _.createdAt.asc else _.createdAt.desc
case "color" => if (exp.order == SortExpressionOrder.Asc) _.color.asc else _.color.desc
case "online" => if (exp.order == SortExpressionOrder.Asc) _.online.asc else _.online.desc
case _ => throw new SortFieldNotSupportedException(s"Sort field '${exp.field}' not supported")
}
}
def filtering(exp: FilterExpression): (HardwareTable) => Rep[Option[Boolean]] = {
exp.field match {
case "serialNumber" => _.serialNumber === exp.value
case "online" => _.online === Try(exp.value.toBoolean).getOrElse(false)
case _ => throw new FilterFieldNotSupportedException(s"Filter field '${exp.field}' not supported")
}
}
def filteringOperator[A](exp: FilterExpression, x: Rep[A], y: A): Rep[Option[Boolean]] = {
exp.operator match {
case FilterExpressionOperator.Equals => x === y
}
}
def all(offset: Int, size: Int, sort: List[SortExpression], filter: List[FilterExpression]): Future[List[Hardware]] = {
var q = Hardwares.to[List]
//sorting
for (exp <- sort) {
try {
q = q.sortBy(sorting(exp))
} catch {
case ex: SortFieldNotSupportedException => return Future.failed(ex)
}
}
//filtering
for (exp <- filter) {
try {
q = q.filter(filtering(exp))
} catch {
case ex: FilterFieldNotSupportedException => return Future.failed(ex)
}
}
//pagination
db.run(q.drop(offset).take(size).result)
}
def exists(serialNumber: String): Future[Boolean] = {
db.run(Hardwares.filter(hw => hw.serialNumber === serialNumber).exists.result)
}
def create(serialNumber: Option[String]): Future[UUID] = {
if (serialNumber.isEmpty) {
db.run(Hardwares.map(hw => (hw.color)) returning Hardwares.map(_.id) += (0))
} else {
//check serial number
val action = (Hardwares.filter(hw => hw.serialNumber === serialNumber).exists.result.flatMap {
case true => DBIO.failed(new EntityAlreadyExistsException("Serialnumber already exists"))
case false => Hardwares.map(hw => (hw.color, hw.serialNumber)) returning Hardwares.map(_.id) += (0, serialNumber.get)
}).transactionally
db.run(action)
}
}
class HardwareTable(tag: Tag) extends Table[Hardware](tag, "hardware") {
def id = column[UUID]("id", O.PrimaryKey)
def createdAt = column[Timestamp]("created_at")
def serialNumber = column[String]("serial_number")
def color = column[Int]("color")
def online = column[Boolean]("online")
def renterCount = column[Int]("renter_count")
def * = (id, createdAt, serialNumber, color, online, renterCount) <> (Hardware.tupled, Hardware.unapply)
def ? = (id.?, createdAt.?, serialNumber.?, color.?, online.?, renterCount.?).shaped.<>({ r => import r._; _1.map(_ => Hardware.tupled((_1.get, _2.get, _3.get, _4.get, _5.get, _6.get))) }, (_: Any) => throw new Exception("Inserting into ? projection not supported."))
}
}
包模型
导入java.sql.Timestamp
导入java.util.UUID
导入javax.inject.inject
导入帮助程序。{FilterExpression,FilterExpressionOperator,SortExpression,SortExpressionOrder}
导入play.api.db.slick.DatabaseConfigProvider
导入helper.exceptions.{EntityAlreadyExistsException,FilterFieldDNNotSupportedException,SortFieldDNNotSupportedException}
导入slick.driver.jdbc配置文件
进口滑溜的。吊起的。订购的
导入scala.concurrent.Future
导入scala.concurrent.ExecutionContext.Implicits.global
导入scala.util.Try
案例级硬件(id:UUID,
createdAt:时间戳,
serialNumber:String,
颜色:Int,
在线:布尔,
租金计算:整数)
类HardwareRepo@Inject()(受保护的val dbConfigProvider:DatabaseConfigProvider){
val dbConfig=dbConfigProvider.get[JdbcProfile]
val db=dbConfig.db
导入dbConfig.driver.api_
private val Hardwares=TableQuery[HardwareTable]
val allowedSorting=Map(“id”->{(hw:Hardware)=>hw.id})
私有def_findById(id:UUID):DBIO[选项[硬件]]=
Hardwares.filter(u.id==id).result.headOption
private def_findBySerialNumber(serialNumber:String):查询[硬件表,硬件,列表]=
hardware.filter(uu.serialNumber==serialNumber).to[List]
def findById(id:UUID):未来[选项[硬件]]=
db.run(_findById(id))
def findBySerialNumber(序列号:字符串):未来[列表[硬件]]=
run(_findBySerialNumber(serialNumber).result)
def排序(exp:SortExpression):(硬件表)=>ColumnOrdered[\uz]={
经验场匹配{
案例“id”=>if(exp.order==SortExpressionOrder.Asc)\ uu.id.Asc else\uu.id.desc
案例“serialNumber”=>if(exp.order==SortExpressionOrder.Asc)\ uuu0.serialNumber.Asc else\ u0.serialNumber.desc
case“createdAt”=>if(exp.order==SortExpressionOrder.Asc)\.createdAt.Asc else\.createdAt.desc
大小写“color”=>if(exp.order==SortExpressionOrder.Asc)\uu.color.Asc else\uu.color.desc
案例“online”=>if(exp.order==SortExpressionOrder.Asc)\ uu.online.Asc else\ uu.online.desc
case=>抛出新的SortFieldNotSupportedException(不支持s“排序字段${exp.field}”)
}
}
def筛选(exp:FilterExpression):(硬件表)=>Rep[选项[布尔]]={
经验场匹配{
案例“serialNumber”=>\uu0.serialNumber===exp.value
case“online”=>\uu.online===Try(exp.value.toBoolean).getOrElse(false)
case=>抛出新的FilterFieldNotSupportedException(不支持s“筛选器字段${exp.field}”)
}
}
def filteringOperator[A](exp:FilterExpression,x:Rep[A],y:A):Rep[Option[Boolean]={
经验运算符匹配{
case FilterExpressionOperator.Equals=>x==y
}
}
def all(偏移量:Int,大小:Int,排序:List[SortExpression],过滤器:List[filteexpression]):Future[List[Hardware]={
var q=硬件。到[列表]
//分类
for(exp返回Future.failed(ex)
}
}
//过滤
for(exp返回Future.failed(ex)
}
}
//分页
db.run(q.drop(偏移量)、take(大小)、result)
}
def存在(serialNumber:字符串):未来[布尔]={
db.run(hardware.filter(hw=>hw.serialNumber===serialNumber).exists.result)
}
def create(serialNumber:Option[String]):Future[UUID]={
if(serialNumber.isEmpty){
db.run(Hardwares.map(hw=>(hw.color))返回Hardwares.map(+uu.id)+=(0))
}否则{
//检查序列号
val操作=(硬件.filter(hw=>hw.serialNumber===serialNumber).存在.result.flatMap{
case true=>DBIO.failed(新EntityAlreadyExistsException(“Serialnumber已存在”))
case false=>Hardwares.map(hw=>(hw.color,hw.serialNumber))返回Hardwares.map(+uu.id)+=(0,serialNumber.get)
}).交易上
db.run(操作)
}
}
类硬件表(tag:tag)扩展表[硬件](tag,“硬件”){
def id=列[UUID](“id”,O.PrimaryKey)
def createdAt=列[时间戳](“创建时”)
def serialNumber=列[字符串](“序列号”)
def color=列[Int](“颜色”)
def online=列[布尔值](“联机”)
def renterCount=列[Int](“出租人计数”)
def*=(id,createdAt,serialNumber,color,online,renterCount)(Hardware.tuple,Hardware.unapply)
def?=(id.?,createdAt.?,serialNumber.?,color.?,online.?,renterCount.?)shaped.({r=>import r.u;1.map(=>Hardware.tupled((1.get,2.get,3.get,4.get,5.get,6.get))),((u5.get,6.Any)=>抛出新异常(“插入?投影不受支持”)
}
}
到res
class HardwareRepo @Inject() (protected val dbConfigProvider: DatabaseConfigProvider) {
with HasDatabaseConfigProvider[JdbcProfile] {
import driver.api._
/*
other repo methods
*/
}