Filtering when using custom column type in Slick

时光怂恿深爱的人放手 提交于 2020-02-20 07:29:44

问题


I'm having some difficulties querying/filtering in Slick 2.1.0 when using a custom column type. A simplified version of my problem:

import scala.slick.driver.MySQLDriver.simple._

sealed class Status(val intValue: Int)
case object Active extends Status(1)
case object Disabled extends Status(2)
case object Deleted extends Status(3)

case class TableMapping(id: Long, status: Status)

class MyTableDefinition(tag: Tag) extends Table[TableMapping](tag, "sometable") {
  implicit val statusColumnType = MappedColumnType.base[Status, Int](statusToInt, intToStatus)

  def id = column[Long]("ID", O.PrimaryKey, O.AutoInc)
  def status = column[Status]("STATUS", O.NotNull, O.Default(Active))
  def * = (id, status) <> (TableMapping.tupled, TableMapping.unapply)

  private def statusToInt(s: Status): Int = s.intValue
  private def intToStatus(i: Int): Status = i match {
    case 1 => Active
    case 2 => Disabled
    case _ => Deleted
  }
}

class MyTableDao {
    val Items = TableQuery[MyTableDefinition]
    def byId(id: Long)(implicit session: Session): Option[TableMapping] = {
      Items.filter(_.status =!= Deleted).firstOption
    }
}

I get a compile error on this:

Items.filter(_.status =!= Deleted).firstOption

The error states:

value =!= is not a member of scala.slick.lifted.Column[Status]
[error] def byId(id: Long)(implicit session: Session): Option[TableMapping] =
  Items.filter(_.status =!= Deleted).firstOption

Any ideas of what I'm doing wrong? Maybe there is a much better way of doing this that I'm not aware of?


回答1:


The thing is that the Scala compiler will look for an implicit convertion for Deleted.type instead of Status.

As Deleted is declared as an object it is not a class, its actual class is Deleted.type, so you just have to help the compiler to understand that is actually a Status. How? You can try

class MyTableDao {
val Items = TableQuery[MyTableDefinition]

def byId(id: Long)(implicit session: Session): Option[TableMapping] =
    Items.filter(_.status =!= Deleted.asInstanceOf[Status]).firstOption
}

That'll do it.

Let me know if it did work, I'm facing a similar problem and I was able to get rid of it doing that.




回答2:


Your custom type mapper needs to be in scope for the DAO; I'd do something like:

trait MyTypeMapper {
  protected implicit val statusColumnType = 
    MappedColumnType.base[Status, Int](_.intValue, intToStatus)

  private def intToStatus(i: Int): Status = i match {
    case 1 => Active
    case 2 => Disabled
    case _ => Deleted
  }
}

and then mix the trait into your table mapper and dao:

class MyTableDefinition(tag: Tag) 
  extends Table[TableMapping](tag, "sometable")
  with MyTypeMapper {...}

class MyTableDao extends MyTypeMapper{...}


来源:https://stackoverflow.com/questions/30483811/filtering-when-using-custom-column-type-in-slick

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!