我正在研究anorm文档(来自播放框架)并且不清楚它是否支持常见的查询用例:动态过滤器,即用户在10个字段的搜索表单中填写2或3个搜索条件
在这种情况下,如何在没有经典字符串操作的情况下动态构造查询?
答案 0 :(得分:13)
是的,我认为Robin Green引用的问题包含答案。只需使用占位符(例如{criterion1}
)定义包含所有可能条件的查询,然后在查询上调用on()
方法,传递Seq
个Option
参数,如上所述接受的答案。
来自Anorm doc的修改示例,假设您有两个条件,但只希望您的查询过滤国家/地区代码而不是资本:
SQL(
"""
select * from Country c
join CountryLanguage l on l.CountryCode = c.Code
where ({countryCode} is null or c.code = {countryCode})
and ({capital} is null or c.capital = {capital});
"""
).on("countryCode" -> Some("FRA"), "capital" -> None)
这应该可以解决问题。
答案 1 :(得分:3)
首先简短回答。假设您在数据库中有一个包含3列的表:name
,email
,pass
。但是,从用户那里,您只有name
和password
,而不是email
。所以制作所有3的选项
val name:Option[String] = Some("alice")
val email:Option[String] = None
val pass:Option[String] = Some("password")
//For db insertion have this:
DB.withConnection { implicit conn =>
SQL("INSERT INTO USERS (name,email,pass) VALUES ({n},{e},{p})").on(
'n -> name, 'e -> email,'p -> pass).executeInsert()
}
执行上述操作时,email
为None
,它会在您的数据库中插入null
。因此,对于您的所有10列,您可以在上面的SQL
语句中定义它们,并在Option
中传递on()
。如果它们中的任何一个是None
,那么它将在数据库中将其作为null
。
如果架构中的列存在NOT NULL
限制,则可能会出现问题。在这种情况下,您可以将getOrElse
用于以下列:
DB.withConnection { implicit conn =>
SQL("INSERT INTO USERS (name,email,pass) VALUES ({n},{e},{p})").on(
'n -> name, 'e -> email.getOrElse("Default Email"),'p -> pass).executeInsert()
以下是关于Play如何将类型转换为数据库类型的理解列表。它可以在对象anorm.ToStatement
中找到:
case Some(bd: java.math.BigDecimal) => stmt.setBigDecimal(index, bd)
case Some(o) => stmt.setObject(index, o)
case None => stmt.setObject(index, null)
case bd: java.math.BigDecimal => stmt.setBigDecimal(index, bd)
case date: java.util.Date => stmt.setTimestamp(index, new java.sql.Timestamp(date.getTime()))
case o => stmt.setObject(index, o)
上面你看,对于None
,它将它视为空。
在SELECT
hmm的情况下,我不知道任何有助于此的anorm功能,但我想简单的String操作可能就足够了:
def getColumns(xs:List[Option[_]]):String = {
val notNone = xs.collect{
case Some(x) => x.toString
}
notNone.mkString(",")
}
然后SQL("SELECT %s from table".format(getColumns(List(nameColumn,emailColumn,passColumn)))
。
虽然这不是你想要的。 Anorm只是一个sql构建库。要做你想做的事,它还必须记住你的表模式(即至少列名......)。我认为没有做过那么多的事情
答案 2 :(得分:0)
Anorm似乎是谨慎操作的前提是您插入普通的旧SQL,没有任何功能,如类型安全或查询构建。它可能不是动态查询的正确工具。构造查询最终必须是字符串操作,因此我建议使用一个为您执行此操作的库。使用Anorm集成任何用于生成SQL语句的库应该很容易。
您可以动态构造查询,并使用类似jOOQ的库将该查询字符串传递给Anorm。作为奖励,您将获得许多数据库的支持。 jOOQ似乎很受欢迎,但可能还有许多其他库可供您使用。如果它不适合您的项目,请完全替换Anorm。