我无法使用slick-3.1.1过滤自定义类型。以下自包含示例说明了我的问题:
object IllustrateSlickQuestion {
val sqlDriver = slick.driver.PostgresDriver
import sqlDriver.api._
trait SomeBaseType {
def value: Int
}
object SomeBaseType {
def apply(value: Int): SomeBaseType = SomeType(value)
}
case class SomeType(value: Int) extends SomeBaseType
implicit val someBaseTypeMappedColumnType = MappedColumnType.base[SomeBaseType, Int](_.value, SomeBaseType.apply)
class SomeTable(tag: Tag) extends Table[(SomeBaseType, Option[SomeBaseType])](tag, "my_table") {
def someColumn = column[SomeBaseType]("some_column")
def someNullableColumn = column[Option[SomeBaseType]]("some_nullable_column")
def * = (someColumn, someNullableColumn)
}
val someTable = TableQuery[SomeTable]
// These selects work:
val compilingSelect1 = someTable.filter(_.someColumn inSet Set(SomeType(42)))
val compilingSelect2 = someTable.filter(_.someNullableColumn inSet Set(SomeType(42)))
// Does not compile:
// [error] type mismatch;
// [error] found : IllustrateSlickQuestion.SomeType
// [error] required: slick.lifted.Rep[?]
// [error] val brokenSelect1 = someTable.filter(_.someColumn === SomeType(42))
val brokenSelect1 = someTable.filter(_.someColumn === SomeType(42))
// Does not compile either:
// [error] see above
val brokenSelect2 = someTable.filter(_.someNullableColumn === SomeType(42))
}
如果我在定义和SomeType
中使用SomeBaseType
代替MappedColumnType
,则此问题就会消失。然而,这不是我真正关心的代码中的一个选项,因为SomeBaseType
表示枚举。因此,我坚持使用inSet
代替===
作为解决方法。
我做错了什么,或者这是Slick中的错误?
答案 0 :(得分:3)
我不确定发生这种情况的确切原因。我认为这与范围内的模糊隐式转换(包括Rep [SomeBaseType]和Rep [Option [SomeBaseType]])有关。所以编译器不知道选择哪个(因此也没有选择)。但我可能是错的。我确实有一些解决方法:
// Adding a type annotation to the filter:
val fixedSelect1 = someTable.filter(_.someColumn === (SomeType(42):SomeBaseType))
// Using a helper method:
def query(someType: Rep[SomeBaseType]) =
someTable.filter(_.someNullableColumn === someType)
query(SomeType(42))
// With compiled queries
val query = Compiled { (someType: Rep[SomeBaseType]) =>
someTable.filter(_.someNullableColumn === someType)
}
答案 1 :(得分:0)
这是一个Scala问题,而不是Slick问题。不建议从对象扩展案例类。您的示例代码未显示如何使用案例类的Exp : let var '=' Exp in Exp { Let $2 $4 $6 }
| Exp1 { Exp1 $1 }
Exp1 : Exp1 '+' Term { Plus $1 $3 }
| Exp1 '-' Term { Minus $1 $3 }
| Term { Term $1 }
Term : Term '*' Factor { Times $1 $3 }
| Term '/' Factor { Div $1 $3 }
| Factor { Factor $1 }
Factor
: int { Int $1 }
| var { Var $1 }
| '(' Exp ')' { Brack $2 }
属性。您是否要覆盖基类value
属性?如果是这样,那么你需要写:
value
但是,您会遇到问题。您可能会发现ADT优于使用case class SomeType(override val value: Int) extends SomeBaseType
:
Enumerator
然后你可能会写这样的东西(未经测试):
sealed trait MyEnum
trait EnumValue1 extends MyEnum
trait EnumValue2 extends MyEnum
trait EnumValue3 extends MyEnum
我的偏好是使用Java枚举:
case class SomeType(myEnum: MyEnum) extends AnyVal with MappedTo[Int]
然后写:
public enum MyEnum {
EnumValue1 , EnumValue2, EnumValue3
}