Mybatis-sql builder

15551 ワード

Sttement Buiders
SelectBuider
Javaプログラマが直面する一番つらいことの一つはJavaコードにSQL文を埋め込むことです。一般にこのようにするのは、SQLが動的に生成されるからです。そうでなければ、それらを外部のファイルまたは格納中に置くことができます。すでにご覧のように、MyBatisはXMLマッピング特性において、動的SQLを生成する強力なソリューションを処理しています。しかし、JavaコードにSQL文の文字列を作成しなければならない場合があります。この場合、MyBatisは別の特性を持っています。典型的なプラス記号、引用符、新行、フォーマット問題、埋め込み条件を減らして、余分なコンマまたはAND接続語を処理する前に、Javaコードの中でSQLを動的に生成するのは悪夢です。 
MyBatis 3はいくつかの異なる理念を導入してこの問題を処理し、SQL文を構築するための方法を呼び出すためのクラスのインスタンスを作成することができます。しかし、私たちのSQLは最後にJavaコードのように見えます。SQL文ではありません。反対に、いくつかの異なるやり方を試してみました。最終的な結果は特定の分野の言語の終了についてです。Javaも現在の形式を実現しつつあります。 
SelectBuiderの秘密
SelectBuider類は不思議ではありません。もしあなたがその仕事の仕組みを知らないなら、いい効果がありません。迷わないでください。どうやって働いているのか見てみましょう。SelectBuiderは、静的導入とTreadLocal変数の組合せを使用して、簡潔な文法を開いて、条件でインターレースを行いやすく、SQLのすべてのフォーマットを保護します。このような方法を作成することができます。 
public String selectBlogsSql() {
  BEGIN(); // Clears ThreadLocal variable
  SELECT("*");
  FROM("BLOG");
  return SQL();
}
これは非常に簡単な例です。静的に構築することを選択するかもしれません。したがって、ここでは複雑な点の例を示している。
private String selectPersonSql() {
  BEGIN(); // Clears ThreadLocal variable
  SELECT("P.ID, P.USERNAME, P.PASSWORD, P.FULL_NAME");
  SELECT("P.LAST_NAME, P.CREATED_ON, P.UPDATED_ON");
  FROM("PERSON P");
  FROM("ACCOUNT A");
  INNER_JOIN("DEPARTMENT D on D.ID = P.DEPARTMENT_ID");
  INNER_JOIN("COMPANY C on D.COMPANY_ID = C.ID");
  WHERE("P.ID = A.ID");
  WHERE("P.FIRST_NAME like ?");
  OR();
  WHERE("P.LAST_NAME like ?");
  GROUP_BY("P.ID");
  HAVING("P.LAST_NAME like ?");
  OR();
  HAVING("P.FIRST_NAME like ?");
  ORDER_BY("P.ID");
  ORDER_BY("P.FULL_NAME");
  return SQL();
}
文字列で接続して上のSQLを構築するのはちょっとややこしいです。たとえば:
"SELECT P.ID, P.USERNAME, P.PASSWORD, P.FULL_NAME, "
"P.LAST_NAME,P.CREATED_ON, P.UPDATED_ON " +
"FROM PERSON P, ACCOUNT A " +
"INNER JOIN DEPARTMENT D on D.ID = P.DEPARTMENT_ID " +
"INNER JOIN COMPANY C on D.COMPANY_ID = C.ID " +
"WHERE (P.ID = A.ID AND P.FIRST_NAME like ?) " +
"OR (P.LAST_NAME like ?) " +
"GROUP BY P.ID " +
"HAVING (P.LAST_NAME like ?) " +
"OR (P.FIRST_NAME like ?) " +
"ORDER BY P.ID, P.FULL_NAME";
そのような文法が好きなら、それを使ってもいいです。それは間違いやすいです。一行ごとに増えていく空間に気をつけてください。現在、このような文法が好きでも、以下の例はJavaの文字列接続よりも簡単であることは間違いない。 
private String selectPersonLike(Person p){
  BEGIN(); // Clears ThreadLocal variable
  SELECT("P.ID, P.USERNAME, P.PASSWORD, P.FIRST_NAME, P.LAST_NAME");
  FROM("PERSON P");
  if (p.id != null) {
  WHERE("P.ID like #{id}");
  }
  if (p.firstName != null) {
  WHERE("P.FIRST_NAME like #{firstName}");
  }
  if (p.lastName != null) {
  WHERE("P.LAST_NAME like #{lastName}");
  }
  ORDER_BY("P.LAST_NAME");
  return SQL();
}
この例には何か特別なところがありますか?よく見ると、偶然に繰り返される「AND」のキーワードや、「WHERE」と「AND」のどちらも選べないことが心配です。上記のステートメントは、例えばすべてのPERSONレコードに対してクエリーを生成し、パラメータのようなIDまたはfirstNameまたはlastName-またはこれらの3つの任意の組合せがある。SelectBuiderはどこに「WHERE」を置くかを理解し、どこで「AND」を使うべきか、そしてすべての文字列接続に気をつけています。最善の場合、これらの方法をどの順番で呼び出しても(例外的にOR()を使う方法しかありません。) 
二つの方法があなたの眼球を引きつけます。BEGIN()とSQL()です。つまり、各SelectBuider方法は、SQL()を呼び出して終了するためにBEGIN()を呼び出すために開始するべきである。もちろん、途中で方法を抽出してあなたの論理を中断することができますが、SQLの生成範囲はBEGIN()の方法で始まり、SQL()の方法で終わるべきです。BEGIN()メソッドは、ThreadLocal変数を整理して、あなたが誤って前の状態を実行しないようにします。そしてSQL()方法はこれらの呼び出しに基づいて、最後のBEGIN()を呼び出してからSQL文を組み立てます。BEGIN()にはRESET()と呼ばれる代替方法があり、それらは同じ作業をしているが、RESET()は特定のコンテキストで読み取りがより良い。 
上の例のようにSelectBuiderを使用するには、以下のような内容を静的に導入する必要があります。 
import static org.apache.ibatis.jdbc.SelectBuilder.*;
これが導入されたら、あなたが使うクラスはSelectBuiderのすべての利用可能な方法を持っています。下表は利用可能な方法の一覧です。 
方法
説明
BEGIN()/RESET()
これらの方法はSelectBuider類のThreadLocalの状態を整理して、新しい語句を構築するつもりです。新しい語句を始める時、BEGIN()が一番いいです。実行中に何らかの理由で(ある条件では、論理を処理するには完全かつ異なる語句が必要かもしれません)ステートメントを整理したい場合、RESET()の読み取りがうまくできます。   
SELECT(String)
SELECT子文を開始または追加します。何度も呼び出すことができます。また、パラメータはSELECT文の後に追加されます。パラメータはコンマ区切りの列名リストと別名ですが、ドライバが許容できるものです。
SELECT_DISTINCT(String)
SELECT子文を開始または追加し、生成されたクエリ文に「DISTINCT」のキーワードを追加します。何度も呼び出すことができます。また、パラメータはSELECT文の後に追加されます。パラメータはコンマ区切りの列名リストと別名ですが、ドライバが許容できるものです。
FROM(String)
開始または追加します。何度も呼び出すことができます。また、パラメータはFROM文の後に追加されます。パラメータは通常、別名またはドライバが許容できる任意の内容を示しています。   
  • JOIN(String)
  • INNER_ジョイン
  • LEFT_アウトレットジョイン
  • RIGHT_アウトレットジョイン
  • 呼び出しの方法に基づいて、適切なタイプの新しいJOINフレーズを追加します。パラメータは、列間の基本的なジョイン接続と条件付き接続を含むことができます。   
    WHERE(String)
    新しいWHERE条件子文を追加し、ANDから直列に接続します。何度も呼び出すことができます。ANDは新しい条件を連絡するために教えてくれます。OR()法を用いてOR条件を分離する。   
    OR()
    ORを使用して現在のWHERE子文の条件を分離します。複数の呼び出しが可能ですが、1行に複数の呼び出しを行うと不安定なSQLが生成されます。
    AND()
    ANDを使用して現在のWHERE字句の条件を分離します。複数の呼び出しが可能ですが、1行に複数の呼び出しを行うと不安定なSQLが生成されます。WHEREとHAVINGの両方が自動的にANDと直列につながっているため、このように使うのは非常に稀であり、それを含むのも完全性のためだけである。   
    GROUT_BY(String)
    新しいGROUTP BY子文を追加して、カンマで繋げます。何度も呼び出すことができます。コンマを使うたびに新しい条件を教えます。   
    HAVING(String)
    新しいHAVING条件をつけて、ANDから直列につなげます。毎回ANDを使って新しい条件を教えます。OR()法を用いてOR条件を分離した。   
    ORDER_BY(String)
    新しいORDER BY子文を追加して、カンマで繋げます。何度も呼び出すことができます。コンマを使うたびに新しい条件を教えます。   
    SQL()
    これは、SQLを生成し、SelectBuiderをリセットする状態(BEGIN()またはRESET()方法が呼び出されるように)を返します。この方法は一回だけ呼び出されます。   
    Sql Buider
    SelectBuiderと似ています。MyBatisも一般的なSql Buiderを含んでいます。SelectBuiderのすべての方法が含まれています。insert、udate、deleteを構築する方法もあります。DeleteProvider、InsertProviderまたはUpdateProviderにSQL文字列を構築するときにこのクラスが有用です。   
    上記の例ではSql Buiderを使用して、簡単に静的に以下の内容を導入するだけでよい。
    import static org.apache.ibatis.jdbc.SqlBuilder.*;
    Sql BuiderはSelectBuiderのすべての方法を含み、以下のような追加の方法がある。
    方法
    説明
    DELETE_FROM(String)
    delete文を開始します。削除するテーブルを指定します。普通はその後ろにWHERE文が付いています。 
    INSERT_INTO(String)
    insert文を開始します。挿入するテーブルを指定します。その後ろには一つ以上のVALES()が付いてきます。   
    SET(String)
    更新文に「set」内容のリストを追加します。
    UPDATE(String)
    udate文を開始します。更新する表を指定します。その後ろには一つ以上のSET()の呼び出しがあります。通常はWHERE()の呼び出しが必要です。
    VALES(String,String)
    insert文に添付してください。最初のパラメータは挿入する列名で、2番目のパラメータは挿入する値です。
    ここではいくつかの例があります。
    public String deletePersonSql() {
      BEGIN(); // Clears ThreadLocal variable
      DELETE_FROM("PERSON");
      WHERE("ID = ${id}");
      return SQL();
    }
    
    public String insertPersonSql() {
      BEGIN(); // Clears ThreadLocal variable
      INSERT_INTO("PERSON");
      VALUES("ID, FIRST_NAME", "${id}, ${firstName}");
      VALUES("LAST_NAME", "${lastName}");
      return SQL();
    }
    
    public String updatePersonSql() {
      BEGIN(); // Clears ThreadLocal variable
      UPDATE("PERSON");
      SET("FIRST_NAME = ${firstName}");
      WHERE("ID = ${id}");
      return SQL();
    }