私は(playフレームワークからの)anormドキュメントを少し勉強していますが、それが一般的なクエリのユースケースをサポートしているかどうかは明確ではありません:動的フィルター、つまりユーザーが10フィールドの検索フォームに2つまたは3つの検索条件を入力します。
この場合、従来の文字列操作なしで動的にクエリを作成するにはどうすればよいですか?
私は(playフレームワークからの)anormドキュメントを少し勉強していますが、それが一般的なクエリのユースケースをサポートしているかどうかは明確ではありません:動的フィルター、つまりユーザーが10フィールドの検索フォームに2つまたは3つの検索条件を入力します。
この場合、従来の文字列操作なしで動的にクエリを作成するにはどうすればよいですか?
はい、ロビングリーンが参照している質問に答えが含まれていると思います。プレースホルダー(例{criterion1}
)を使用して可能なすべての基準でクエリを定義し、クエリでメソッドを呼び出して、受け入れられた回答に記載されているようにon()
実際Seq
のパラメーターを渡します。Option
Anormドキュメントの例を変更しました。ただし、2つの基準があり、クエリで国コードのみをフィルタリングし、首都ではフィルタリングしないと仮定します。
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)
それでうまくいくはずです。
最初に短い答え。データベースに、、、、の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
、nullと見なされます。
うーん、ここSELECT
で役立つアノーム機能はわかりませんが、単純な文字列操作で十分だと思います。
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構築ライブラリです。やりたいことをするためには、テーブルスキーマ(つまり、少なくとも列名..)も覚えておく必要があります。私はアノームがそれをすべて行うように作られているとは思いません
Anormは、型安全性やクエリ構築などの機能を使用せずに、単純な古いSQLを挿入することを前提として明確に動作しているようです。動的クエリにはおそらく適切なツールではありません。クエリの作成は、最終的には文字列操作である必要があるため、これを行うライブラリを使用することをお勧めします。SQLステートメントを生成するためのライブラリをAnormと簡単に統合できるはずです。
クエリを動的に作成し、そのクエリ文字列をjOOQなどのライブラリを使用してAnormに渡すことができます。ボーナスとして、多くのデータベースのサポートを利用できます。jOOQは人気があるようですが、代わりに使用できるライブラリは他にもたくさんあるでしょう。または、プロジェクトに適していない場合は、Anormを完全に置き換えます。