我遇到了可空列比较的问题。
如果某些列是Option [T],我想知道如何将这些列上的===
操作转换为sql。
有两种可能性:null值(scala中为None)和非null值。
在null值的情况下,sql应该使用is
而不是=
。
但是,在下列情况下,光滑无法正确处理它。
这是代码(使用H2数据库):
object Test1 extends Controller {
case class User(id: Option[Int], first: String, last: String)
class Users(tag: Tag) extends Table[User](tag, "users") {
def id = column[Int]("id",O.Nullable)
def first = column[String]("first")
def last = column[String]("last")
def * = (id.?, first, last) <> (User.tupled, User.unapply)
}
val users = TableQuery[Users]
def find_u(u:User) = DB.db.withSession{ implicit session =>
users.filter( x=> x.id === u.id && x.first === u.first && x.last === u.last ).firstOption
}
def t1 = Action {
DB.db.withSession { implicit session =>
DB.createIfNotExists(users)
val u1 = User(None,"123","abc")
val u2 = User(Some(1232),"123","abc")
users += u1
val r1 = find_u(u1)
println(r1)
val r2 = find_u(u2)
println(r2)
}
Ok("good")
}
}
我打印出sql。它是第一个find_u
的结果。
[debug] s.s.j.J.statement - Preparing statement: select x2."id", x2."first", x2."last" from "users" x2 where (
(x2."id" = null) and (x2."first" = '123')) and (x2."last" = 'abc')
请注意,此处(x2."id" = null)
不正确。它应该是(x2."id" is null)
。
更新
是否可以仅以自动方式比较非空字段?忽略那些空列。
例如。在User(None,"123","abc")
的情况下,只执行where (x2."first" = '123')) and (x2."last" = 'abc')
答案 0 :(得分:1)
Slick使用三值逻辑。这显示了涉及可空列的时间。在这方面,它不遵循Scala语义,而是使用SQL语义。所以(x2."id" = null)
在这些设计决策下确实是正确的。要使用x.id.isEmpty
进行严格的NULL检查。为了严格比较,
(if(u.id.isEmpty) x.id.isEmpty else (x.id === u.id))
<强>更新强>
仅在用户标识为非空时才进行比较
(u.id.isEmpty || (x.id === u.id)) && ...