ResultHandler<RES> インターフェース

pureQuery が照会結果を表すオブジェクトを作成するのに使用できる com.ibm.pdq.runtime.handlers.ResultHandler<RES> インターフェースのインプリメンテーションを作成できます。
ResultHandler<RES> インターフェースは 1 つのメソッドのみ宣言します。
public T handle (ResultSet resultSet);

pureQuery は handle() メソッドを呼び出し、行を表すオブジェクトを作成します。pureQuery は照会結果を java.sql.ResultSet のインスタンスのメソッドに渡します。ResultHandler<RES> のインプリメンテーションを作成する場合は、このメソッドを実装して、ResultSet インスタンスの照会結果を表すオブジェクト・タイプ <RES> を作成し、戻します。

ハンドラーをパラメーターとして指定する場合、そのパラメーターはメソッド・シグニチャーの最後のパラメーターでなければなりません。ParameterHandler と一緒に ResultHandler をパラメーターとして指定する場合、これらのパラメーターはメソッド・シグニチャーの最後の 2 つのパラメーターでなければなりません。

データ・ソースを照会するアプリケーションが照会結果全体を String オブジェクトとして他のアプリケーションに送信するとします。他方のアプリケーションは、String に一連のオブジェクトが JSON 形式で含まれていることを期待します。ResultHandler<RES> インターフェースの handle() メソッドを使用すると、オブジェクトの配列を表す単一の JSON ストリングに照会結果を変換できます。

package customHandlers;

import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;

import com.ibm.pdq.runtime.handlers.ResultHandler;

public class JSONResultHandler implements ResultHandler<String>
{
  // The ResultHandler<RES> interface defines this method
  public String handle (ResultSet rs)
  {
    StringBuffer stringBuffer = new StringBuffer ();
    try {
      ResultSetMetaData resultSetMetaData = rs.getMetaData ();
      int columnCount = resultSetMetaData.getColumnCount ();
      boolean first = true;
      stringBuffer.append ("[");
      while (rs.next ()) {
        // すべての行オブジェクト (最後のものは除く) の後には "," が続きます。
        if (!first) stringBuffer.append (",");
        first = false;
        stringBuffer.append ("{");
        for (int x = 1; x <= columnCount; x++) {
          stringBuffer.append ("¥"");
          stringBuffer.append (toJSONString (resultSetMetaData.getColumnLabel (x)));
          stringBuffer.append ("¥":¥"");
          stringBuffer.append (toJSONString (rs.getString (x)));
          stringBuffer.append ("¥"");
          if (x < columnCount) stringBuffer.append (",");
        }
        stringBuffer.append ("}");
      }
      stringBuffer.append ("]");
    }
    catch (SQLException e) {
      throw new RuntimeException ("The JSONResultHandler failed to create a JSON string from the query results.", e);
    }
    return stringBuffer.toString ();
  }

  private String toJSONString (String value)
  {
    if (value != null) {
      int valueLength = value.length ();
      StringBuffer sb = new StringBuffer (valueLength);
      for (int i = 0; i < valueLength; i++) {
        char c = value.charAt (i);
        switch (c) {
          case '¥¥':
            sb.append ("¥¥¥¥");
          break;
          case '"':
            sb.append ("¥¥¥"");
          break;
          case '/':
            sb.append ("¥¥/");
          break;
          case 0x08:
            sb.append ("¥¥b");
          break;
          case 0xC:
            sb.append ("¥¥f");
          break;
          case 0xA:
            sb.append ("¥¥n");
          break;
          case 0xD:
            sb.append ("¥¥r");
          break;
          case 0x9:
            sb.append ("¥¥t");
          break;
          default:
            sb.append (c);
          break;
        }
      }
      return sb.toString ();
    }
    else
      return null;
  }

}

以下は、JSONResultHandler が生成できる JSON ストリングの例です。

[{"DEPTNO":"A00","DEPTNAME":"SPIFFY COMPUTER SERVICE DIV.","MGRNO":"000010","ADMRDEPT":"A00","LOCATION":"null"},
{"DEPTNO":"B01","DEPTNAME":"PLANNING","MGRNO":"000020",
"ADMRDEPT":"A00","LOCATION":"null"},...]

アノテーション付きメソッドを用いた ResultHandler オブジェクトの使用

アノテーション付きメソッドを使用するために ResultHandler オブジェクトを指定するには 2 つの方法があります。

@Handler アノテーションの使用
@Select または @Update アノテーションを使用することに加えて、@Handler アノテーションをメソッドの定義に提供します。 @Handler アノテーションでは、ResultHandler インプリメンテーションのクラスを指定します。 指定するハンドラーは public な、引数なしコンストラクターでなければなりません。 pureQuery は引数なしコンストラクターを使用して、ハンドラーの単一インスタンスを作成し、そのインスタンスはアノテーション付きメソッドのすべての呼び出しによって使用されます。
例えば、JSONResultHandler を使用したアノテーション付きメソッドを宣言できます。 pureQuery は引数なしコンストラクターを使用してハンドラーをインスタンス化します。
@Select(sql = “select * from employee where workdept = ?1.departmentNumber") 
@Handler(resultHandler = customHandlers.JSONResultHandler.class) 
String toJSON(DepartmentBean department);
メソッド・パラメーターの使用
代わりに、ResultHandler インプリメンテーションをアノテーション付きメソッド定義のパラメーターとして指定できます。アプリケーションがメソッドを呼び出すとき、メソッドは、実際のインスタンスを pureQuery が使用するために提供できます。

ハンドラーをパラメーターとして指定する場合、そのパラメーターはメソッド・シグニチャーの最後のパラメーターでなければなりません。

例えば、Iterator<EmployeeBean> に照会結果を取得し、Iterator<EmployeeBean> が照会結果の 11 行目から 20 行目のみ含むようにするとします。com.ibm.pdq.runtime.data.handlers.IteratorPagingResultHandler<RES> を使用します。 インターフェースには、IteratorPagingResultHandler<RES> のインスタンスをパラメーターとして取るアノテーション付きメソッドを定義できます。

@Select(sql = "select * from employee where workdept = ?1.departmentNumber")
  Iterator<EmployeeBean> selectEmployeesInDepartment(DepartmentBean department, IteratorPagingResultHandler resultHandler);

結果の 11 行目から 20 行目を含むようにする場合は、以下のようにメソッドを呼び出します。

//照会を実行して 11 から 20 行目のイテレーターを作成する
Iterator<EmployeeBean> employees = face.selectEmployeesInDepartment(theDepartment, new IteratorPagingResultHandler(EmployeeBean.class, 11, 20));

複数の ResultHandler<RES> インプリメンテーションを使用して単一のアノテーション付きメソッド宣言を使用する場合は、汎用 ResultHandler<RES> を使用するアノテーション付きメソッドをシグニチャーに定義できます。

@Select(sql = "select * from employee where workdept = ?1.departmentNumber")
  <RES> RES selectEmployeesInDepartment(DepartmentBean department, ResultHandler<RES> resultHandler);

その後、特定のタイプの ResultHandler オブジェクトを渡すことにより、メソッドを呼び出すことができます。

Iterator<EmployeeBean> employee = face.selectEmployeesInDepartment(theDepartment, new IteratorPagingResultHandler(EmployeeBean.class, 11, 20));

インライン・メソッドを用いた ResultHandler オブジェクトの使用

Iterator<EmployeeBean> に照会結果を取得し、Iterator<EmployeeBean> が照会結果の 11 行目から 20 行目のみ含むようにするとします。 com.ibm.pdq.runtime.data.handlers.IteratorPagingResultHandler<RES> を使用します。 IteratorPagingResultHandler<RES> のインスタンスをパラメーターとして取るインライン・メソッドを定義できます。
Connection con = DriverManager.getConnection(...);
  Data d = DataFactory.getData(con);

//照会を実行して 11 から 20 行目のイテレーターを作成する
  Iterator<EmployeeBean> employees = d.query("select * from employee where workdept = ?1.departmentNumber",
         theDepartment, new IteratorPagingResultHandler(EmployeeBean.class,11, 20));

フィードバック