13

私は(playフレームワークからの)anormドキュメントを少し勉強していますが、それが一般的なクエリのユースケースをサポートしているかどうかは明確ではありません:動的フィルター、つまりユーザーが10フィールドの検索フォームに2つまたは3つの検索条件を入力します。

この場合、従来の文字列操作なしで動的にクエリを作成するにはどうすればよいですか?

4

3 に答える 3

14

はい、ロビングリーンが参照している質問に答えが含まれていると思います。プレースホルダー(例{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)

それでうまくいくはずです。

于 2013-08-19T06:56:51.937 に答える
3

最初に短い答え。データベースに、、、、の3つの列を含むテーブルがあるとnameemailます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構築ライブラリです。やりたいことをするためには、テーブルスキーマ(つまり、少なくとも列名..)も覚えておく必要があります。私はアノームがそれをすべて行うように作られているとは思いません

于 2013-08-19T07:24:30.750 に答える
0

Anormは、型安全性やクエリ構築などの機能を使用せずに、単純な古いSQLを挿入することを前提として明確に動作しているようです。動的クエリにはおそらく適切なツールではありません。クエリの作成は、最終的には文字列操作である必要があるため、これを行うライブラリを使用することをお勧めします。SQLステートメントを生成するためのライブラリをAnormと簡単に統合できるはずです。

クエリを動的に作成し、そのクエリ文字列をjOOQなどのライブラリを使用してAnormに渡すことができます。ボーナスとして、多くのデータベースのサポートを利用できます。jOOQは人気があるようですが、代わりに使用できるライブラリは他にもたくさんあるでしょう。または、プロジェクトに適していない場合は、Anormを完全に置き換えます。

于 2013-08-19T09:35:30.750 に答える