ResultHandler<RES> (Schnittstelle)

Sie können eine Implementierung der Schnittstelle com.ibm.pdq.runtime.handlers.ResultHandler<RES> erstellen, mit der pureQuery ein Objekt erstellen kann, das ein Abfrageergebnis darstellt.
Die Schnittstelle ResultHandler<RES> deklariert nur eine Methode:
public T handle (ResultSet resultSet);

pureQuery ruft die Methode handle() auf, um ein Objekt zu erstellen, das ein Abfrageergebnis darstellt. pureQuery übergibt die Abfrageergebnisse in einer Instanz von java.sql.ResultSet an die Methode. Wenn Sie eine Implementierung von ResultHandler<RES> erstellen, implementieren Sie diese Methode, um ein Objekt des Typs <RES> zu erstellen und zurückzugeben, das ein Abfrageergebnis in der ResultSet-Instanz darstellt.

Wenn Sie einen Handler als Parameter angeben, muss der Parameter der letzte Parameter in der Methodenkennung sein. Wenn Sie ResultHandler zusammen mit ParameterHandler als Parameter angeben, müssen die Handler die beiden letzten Parameter in der Methodenkennung sein.

Angenommen, eine Anwendung, die eine Datenquelle abfragt, sendet die Ergebnisse der Abfragen vollständig als String-Objekte an eine andere Anwendung. Diese andere Anwendung erwartet, dass die Zeichenfolge eine Reihe von Objekten im JSON-Format enthält. Sie können die Abfrageergebnisse mit der Methode handle() in der Schnittstelle ResultHandler<RES> in eine einzelne JSON-Zeichenfolge konvertieren, die ein Array von Objekten darstellt.

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 ()) {
        // All row objects, except the last, are followed by a ","
        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;
  }

}

Es folgt ein Beispiel für eine JSON-Zeichenfolge, die JSONResultHandler erstellen könnte:

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

ResultHandler-Objekte mit mit Annotationen versehenen Methoden verwenden

Es gibt zwei Arten, ResultHandler-Objekte für mit Annotationen versehene Methoden anzugeben.

Annotation @Handler verwenden
Stellen Sie die Annotation @Handler in der Definition der Methode zusätzlich zur Verwendung der Annotation @Select oder @Update bereit. Geben Sie in der Annotation @Handler die Klasse Ihrer ResultHandler-Implementierung an. Der von Ihnen angegebene Handler muss einen allgemein zugänglichen No-Arg-Konstruktor haben. pureQuery verwendet den No-Arg-Konstruktor zum Erstellen einer einzelnen Instanz des Handler und diese Instanz wird von allen Aufrufen der mit Annotationen versehenen Methode verwendet.
Sie könnten z. B. eine mit Annotationen versehene Methode deklarieren, die JSONResultHandler verwendet. pureQuery instanziiert den Handler mit dem No-Arg-Konstruktor.
@Select(sql = “select * from employee where workdept = ?1.departmentNumber") 
@Handler(resultHandler = customHandlers.JSONResultHandler.class) 
String toJSON(DepartmentBean department);
Methodenparameter verwenden
Sie können die RowHandler-Implementierung auch als Parameter der Definition einer mit Annotationen versehenen Methode angeben. Wenn Ihre Anwendung die Methode aufruft, kann sie die tatsächliche Instanz bereitstellen, die pureQuery verwendet.

Wenn Sie einen Handler als Parameter angeben, muss der Parameter der letzte Parameter in der Methodenkennung sein.

Angenommen, Sie wollen die Ergebnisse Ihrer Abfrage in Iterator<EmployeeBean> abrufen und Sie wollen in Iterator<EmployeeBean> nur die Zeilen 11 bis 20 der Ergebnisse aufnehmen. Sie könnten com.ibm.pdq.runtime.data.handlers.IteratorPagingResultHandler<RES> verwenden. Sie könnten in einer Schnittstelle eine mit Annotationen versehene Methode definieren, die eine Instanz von IteratorPagingResultHandler<RES> als Parameter verwendet.

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

Wenn Sie die Zeilen 11 bis 20 der Ergebnisse abrufen wollen, können Sie die Methode wie folgt aufrufen:

// Execute the query and create an iterator for rows 11-20
Iterator<EmployeeBean> employees = face.selectEmployeesInDepartment(theDepartment, new IteratorPagingResultHandler(EmployeeBean.class, 11, 20));

Wenn Sie eine einzelne Deklaration einer mit Annotationen versehenen Methode mit mehreren ResultHandler<RES>-Implementierungen verwenden wollen, können Sie eine mit Annotationen versehene Methode definieren, die die generische ResultHandler<RES>-Implementierung in der Signatur verwendet:

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

Sie können dann die Methode aufrufen, indem Sie ein ResultHandler-Objekt eines bestimmten Typs übergeben:

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

ResultHandler-Objekte mit integrierten Methoden verwenden

Angenommen, Sie wollen die Ergebnisse Ihrer Abfrage in Iterator<EmployeeBean> abrufen und Sie wollen in Iterator<EmployeeBean> nur die Zeilen 11 bis 20 der Ergebnisse aufnehmen. Sie könnten com.ibm.pdq.runtime.data.handlers.IteratorPagingResultHandler<RES> verwenden. Sie könnten eine integrierte Methode definieren, die eine Instanz von IteratorPagingResultHandler<RES> als Parameter verwendet.
Connection con = DriverManager.getConnection(...);
  Data d = DataFactory.getData(con);

// Execute the query and create an iterator for rows 11-20
  Iterator<EmployeeBean> employees = d.query("select * from employee where workdept = ?1.departmentNumber",
         theDepartment, new IteratorPagingResultHandler(EmployeeBean.class,11, 20));

Feedback