Ibatis-dynamic-sql

提供:Dev Guides
移動先:案内検索

iBATIS-ダイナミックSQL

ダイナミックSQLは、iBATISの非常に強力な機能です。 パラメータオブジェクトの状態に基づいてWHERE句の条件を変更する必要がある場合があります。 そのような状況では、iBATISは、SQLの再利用性と柔軟性を強化するために、マップされたステートメント内で使用できる動的SQLタグのセットを提供します。

すべてのロジックは、いくつかの追加タグを使用して.XMLファイルに配置されます。 以下は、SELECTステートメントが2つの方法で機能する例です-

  • IDを渡すと、そのIDに対応するすべてのレコードが返されます。 *それ以外の場合、従業員IDがNULLに設定されているすべてのレコードが返されます。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sqlMap PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN" "http://ibatis.apache.org/dtd/sql-map-2.dtd">

<sqlMap namespace="Employee">

   <select id="findByID" resultClass="Employee">
      SELECT* FROM EMPLOYEE

      <dynamic prepend="WHERE ">
         <isNull property="id">
            id IS NULL
         </isNull>

         <isNotNull property="id">
            id = #id#
         </isNotNull>
      </dynamic>

   </select>
</sqlMap>

次のように<isNotEmpty>タグを使用して条件を確認できます。 ここでは、渡されたプロパティが空でない場合にのみ条件が追加されます。

..................
<select id="findByID" resultClass="Employee">
   SELECT *FROM EMPLOYEE

   <dynamic prepend="WHERE ">
      <isNotEmpty property="id">
         id = #id#
      </isNotEmpty>
   </dynamic>

</select>
..................

従業員のIDや名前を選択できるクエリが必要な場合、SELECTステートメントは次のようになります-

..................
<select id="findByID" resultClass="Employee">
   SELECT* FROM EMPLOYEE

   <dynamic prepend="WHERE ">
      <isNotEmpty prepend="AND" property="id">
         id = #id#
      </isNotEmpty>

      <isNotEmpty prepend="OR" property="first_name">
         first_name = #first_name#
      </isNotEmpty>
   </dynamic>
</select>
..................

動的SQLの例

次の例は、動的SQLを使用してSELECTステートメントを作成する方法を示しています。 考慮してください、MySQLには次のEMPLOYEEテーブルがあります-

CREATE TABLE EMPLOYEE (
   id INT NOT NULL auto_increment,
   first_name VARCHAR(20) default NULL,
   last_name  VARCHAR(20) default NULL,
   salary     INT  default NULL,
   PRIMARY KEY (id)
);

次のように、このテーブルにはレコードが1つだけあるとします-

mysql> select * from EMPLOYEE;
+----+------------+-----------+--------+
| id | first_name | last_name | salary |
+----+------------+-----------+--------+
|  1 | Zara       | Ali       |   5000 |
+----+------------+-----------+--------+
1 row in set (0.00 sec)

従業員POJOクラス

読み取り操作を実行するには、次のようにEmployee.javaにEmployeeクラスを用意します-

public class Employee {
   private int id;
   private String first_name;
   private String last_name;
   private int salary;

  /*Define constructors for the Employee class.*/
   public Employee() {}

   public Employee(String fname, String lname, int salary) {
      this.first_name = fname;
      this.last_name = lname;
      this.salary = salary;
   }

  /*Here are the method definitions*/
   public int getId() {
      return id;
   }

   public String getFirstName() {
      return first_name;
   }

   public String getLastName() {
      return last_name;
   }

   public int getSalary() {
      return salary;
   }

}/*End of Employee*/

Employee.xmlファイル

iBATISを使用してSQLマッピングステートメントを定義するには、次の変更された<select>タグをEmployee.xmlに追加し、このタグ定義内で、ダイナミックSQL SELECTクエリを実行するためにIbatisReadDy.javaで使用される「id」を定義しますデータベース。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sqlMap PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN" "http://ibatis.apache.org/dtd/sql-map-2.dtd">

<sqlMap namespace="Employee">
   <select id="findByID" resultClass="Employee">
      SELECT * FROM EMPLOYEE

      <dynamic prepend="WHERE ">
         <isNotNull property="id">
            id = #id#
         </isNotNull>
      </dynamic>

   </select>
</sqlMap>

上記のSELECT文は2つの方法で動作します-

  • IDを渡すと、そのIDに対応するレコードが返されます。それ以外の場合は、すべてのレコードが返されます。

IbatisReadDy.javaファイル

このファイルには、従業員テーブルから条件付きレコードを読み取るためのアプリケーションレベルのロジックがあります-

import com.ibatis.common.resources.Resources;
import com.ibatis.sqlmap.client.SqlMapClient;
import com.ibatis.sqlmap.client.SqlMapClientBuilder;

import java.io.*;
import java.sql.SQLException;
import java.util.*;

public class IbatisReadDy{
   public static void main(String[] args) throws IOException,SQLException{

      Reader rd=Resources.getResourceAsReader("SqlMapConfig.xml");
      SqlMapClient smc=SqlMapClientBuilder.buildSqlMapClient(rd);

     /* This would read all records from the Employee table.*/
      System.out.println("Going to read records.....");
      Employee rec = new Employee();
      rec.setId(1);

      List <Employee> ems = (List<Employee>)
         smc.queryForList("Employee.findByID", rec);
      Employee em = null;

      for (Employee e : ems) {
         System.out.print("  " + e.getId());
         System.out.print("  " + e.getFirstName());
         System.out.print("  " + e.getLastName());
         System.out.print("  " + e.getSalary());
         em = e;
         System.out.println("");
      }
      System.out.println("Records Read Successfully ");
   }
}

コンパイルと実行

上記のソフトウェアをコンパイルして実行する手順は次のとおりです。 コンパイルと実行に進む前に、PATHとCLASSPATHが適切に設定されていることを確認してください。

  • 上記のようにEmployee.xmlを作成します。
  • 上記のようにEmployee.javaを作成し、コンパイルします。
  • 上記のようにIbatisReadDy.javaを作成してコンパイルします。
  • IbatisReadDyバイナリを実行してプログラムを実行します。

次の結果が得られ、EMPLOYEEテーブルからレコードが読み取られます。

Going to read records.....
   1  Zara  Ali  5000
Record Reads Successfully

_smc.queryForList( "Employee.findByID"、null)_として null を渡して上記の例を試してください。

iBATIS OGNL式

iBATISは、強力なOGNLベースの式を提供して、他のほとんどの要素を排除します。

  • ifステートメント
  • 選択、いつ、それ以外の場合
  • whereステートメント *foreachステートメント

ifステートメント

動的SQLで最もよく行うことは、where句の一部を条件付きで含めることです。 たとえば-

<select id="findActiveBlogWithTitleLike" parameterType="Blog" resultType="Blog">
   SELECT* FROM BLOG
   WHERE state = 'ACTIVE.

   <if test="title != null">
      AND title like #{title}
   </if>

</select>

このステートメントは、オプションのテキスト検索タイプの機能を提供します。 タイトルを渡さない場合、すべてのアクティブなブログが返されます。 ただし、タイトルを渡すと、指定された like 条件のタイトルが検索されます。

次のように、複数の if 条件を含めることができます-

<select id="findActiveBlogWithTitleLike" parameterType="Blog" resultType="Blog">
   SELECT * FROM BLOG
   WHERE state = 'ACTIVE.

   <if test="title != null">
      AND title like #{title}
   </if>

   <if test="author != null">
      AND author like #{author}
   </if>

</select>

選択、タイミング、およびその他のステートメント

iBATISは、Javaのswitchステートメントに似た choose 要素を提供します。 多くのオプションから1つのケースのみを選択するのに役立ちます。

次の例では、タイトルが指定されている場合はタイトルのみで検索し、タイトルが指定されている場合は作成者のみで検索します。 どちらも提供されていない場合は、注目のブログのみが返されます-

<select id="findActiveBlogWithTitleLike" parameterType="Blog" resultType="Blog">
   SELECT *FROM BLOG
   WHERE state = 'ACTIVE.

   <choose>
      <when test="title != null">
         AND title like #{title}
      </when>

      <when test="author != null and author.name != null">
         AND author like #{author}
      </when>

      <otherwise>
         AND featured = 1
      </otherwise>
   </choose>

</select>

whereステートメント

前の例を見て、どの条件も満たされない場合はどうなるかを確認してください。 あなたはこのように見えるSQLで終わるでしょう-

SELECT* FROM BLOG
WHERE

これは失敗しますが、iBATISには1つの簡単な変更で簡単なソリューションがあり、すべてが正常に機能します-

<select id="findActiveBlogLike" parameterType="Blog" resultType="Blog">
   SELECT * FROM BLOG

   <where>
      <if test="state != null">
         state = #{state}
      </if>

      <if test="title != null">
         AND title like #{title}
      </if>

      <if test="author != null>
         AND author like #{author}
      </if>
   </where>

</select>
*where* 要素は、含むタグがコンテンツを返す場合にのみ_WHERE_を挿入します。 さらに、そのコンテンツが_AND_または_ORで始まる場合、それを削除することを認識しています。

foreachステートメント

foreach要素を使用すると、コレクションを指定し、要素の本体内で使用できるアイテム変数とインデックス変数を宣言できます。

また、開始文字列と終了文字列を指定し、繰り返しの間に配置するセパレータを追加することもできます。 次のように IN 条件を構築できます-

<select id="selectPostIn" resultType="domain.blog.Post">
   SELECT *
   FROM POST P
   WHERE ID in

   <foreach item="item" index="index" collection="list"
      open="(" separator="," close=")">
      #{item}
   </foreach>

</select>