Slick 3.0.2自定义列Option类型过滤编译失败求助
你遇到的问题是因为Slick无法自动为Rep[Option[Age]]找到合适的===方法重载——虽然你已经定义了TypedType[Age],但对于Option包裹的自定义类型,需要调整比较方式或者显式提供类型支持。下面是几种可行的解决方案:
方案1:通过映射后的基础类型进行过滤
既然你的Age类型是映射到Int的,你可以直接针对底层的Int值进行过滤,这样Slick能轻松处理:
def byId(id: Long)(implicit session: Session): Option[User] = { users.filter(_.age.map(_.value) === 21).firstOption }
这个写法会生成对应的SQL WHERE age = 21,完全符合你的需求,而且不需要额外的隐式定义。
方案2:使用LiteralColumn显式包装右侧值
如果你想直接比较Option[Age]类型,可以用LiteralColumn把Some(Age(21))包装成Slick能识别的Rep类型:
import slick.lifted.LiteralColumn def byId(id: Long)(implicit session: Session): Option[User] = { users.filter(_.age === LiteralColumn(Some(Age(21)))).firstOption }
这样Slick就能匹配到正确的===方法重载,因为两边都是Rep[Option[Age]]类型了。
方案3:确认隐式类型推导是否完整
虽然你已经定义了TypedType[Age],Slick理论上会自动推导TypedType[Option[Age]],但有时候在3.0.2版本中可能需要显式确保相关隐式被导入。你可以检查是否已经导入了MySQLDriver.simple._下的所有隐式(你已经导入了),如果还是有问题,可以尝试显式添加:
import scala.slick.lifted.OptionColumnExtensionMethods._
不过通常这个步骤不是必须的,前两种方案更直接有效。
为什么原来的写法不行?
当你写_.age === Some(Age(21))时,左边是Rep[Option[Age]],右边是普通的Option[Age],Slick无法自动将普通的Option值转换为对应的Rep类型,也找不到支持这种跨类型比较的===方法。通过上面的方案,要么转换为基础类型比较,要么把右侧值包装成Rep类型,就能解决这个问题。
内容的提问来源于stack exchange,提问作者adu

