Interface ResultHandler<RES>

Vous pouvez créer une implémentation de l'interface com.ibm.pdq.runtime.handlers.ResultHandler<RES> utilisable par pureQuery pour créer un objet représentant le résultat d'une requête.
L'interface ResultHandler<RES> ne déclare qu'une méthode :
public T handle (ResultSet resultSet);

pureQuery appelle la méthode handle() pour créer un objet représentant le résultat d'une requête. pureQuery transmet les résultats de la requête à la méthode dans une instance de java.sql.ResultSet. Si vous créez une implémentation de ResultHandler<RES>, implémentez cette méthode pour créer et retourner un objet de type <RES> représentant le résultat d'une requête dans une instance ResultSet.

Lorsque vous spécifiez un gestionnaire comme paramètre, le paramètre doit être le dernier paramètre de la signature de méthode. Si vous spécifiez ResultHandler avec ParameterHandler comme paramètres, les gestionnaires doivent être les deux derniers paramètres de la signature de la méthode.

Imaginons une application analysant une source de données et envoyant les résultats des analyses entières en tant qu'objets String dans une autre application. Cette autre application attend que la chaîne contienne une série d'objets au format JSON. Vous pouvez utiliser la méthode handle() de l'interface ResultHandler<RES> pour convertir les résultats de l'analyse en une chaîne JSON unique représentant une matrice d'objets.

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>
{
  // L'interface ResultHandler<RES> définit cette méthode
  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 ()) {
        // Tous les objets de ligne, à l'exception du dernier, sont suivis d'une virgule ","
        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;
  }

}

Voici un exemple de chaîne JSON pouvant être produit par JSONResultHandler :

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

Utilisation des objets ResultHandler avec les méthodes annotées

Il existe deux manières de spécifier des objets ResultHandler pour les méthodes annotées.

Utilisez l'annotation @Handler
Fournissez l'annotation @Handler dans la définition de la méthode en complément de l'annotation @Select ou @Update. Dans l'annotation @Handler, spécifiez la classe de votre implémentation ResultHandler. Le gestionnaire spécifié doit posséder un constructeur public sans argument. pureQuery utilise le constructeur sans argument pour créer une instance unique du gestionnaire. Cette instance est utilisée par toutes les invocations de la méthode annotée.
Par exemple, vous pouvez déclarer une méthode annotée utilisant JSONResultHandler. pureQuery instancie le gestionnaire avec le constructeur sans argument.
@Select(sql = “select * from employee where workdept = ?1.departmentNumber") 
@Handler(resultHandler = customHandlers.JSONResultHandler.class) 
String toJSON(DepartmentBean department);
Utilisez les paramètres de méthode
Vous pouvez sinon spécifier l'implémentation ResultHandler en tant que paramètre de la définition de méthode annotée. Lorsque votre application appelle la méthode, elle peut fournir l'instance réelle à utiliser par pureQuery.

Lorsque vous spécifiez un gestionnaire comme paramètre, le paramètre doit être le dernier paramètre de la signature de méthode.

Par exemple, supposons que vous voulez obtenir les résultats de votre analyse dans Iterator<EmployeeBean>, et que vous voulez uniquement voir les lignes 11 à 20 des résultats. Vous pouvez utiliser com.ibm.pdq.runtime.data.handlers.IteratorPagingResultHandler<RES>. Dans une interface, vous pouvez définir une méthode annotée prenant une instance de IteratorPagingResultHandler<RES> comme paramètre.

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

Si vous voulez les lignes 11 à 20 des résultats, appelez la méthode comme suit :

// Exécutez l'analyse et créez un itérateur pour les lignes 11 à 20
Iterator<EmployeeBean> employees = face.selectEmployeesInDepartment(theDepartment, new IteratorPagingResultHandler(EmployeeBean.class, 11, 20));

Si vous souhaitez utiliser une déclaration de méthode annotée unique dotée de plusieurs implémentations ResultHandler<RES>, vous pouvez définir une méthode annotée utilisant l'objet ResultHandler<RES> générique dans la signature :

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

Vous pouvez ensuite invoquer la méthode en transmettant un objet ResultHandler de type spécifique :

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

Utilisation des objets ResultHandler avec les méthodes intégrées

Supposons que vous voulez obtenir les résultats de l'analyse dans Iterator<EmployeeBean> et que vous voulez uniquement voire les lignes 11 à 20 des résultats. Vous pouvez utiliser com.ibm.pdq.runtime.data.handlers.IteratorPagingResultHandler<RES>. Vous pouvez définir une méthode intégrée prenant une instance IteratorPagingResultHandler<RES> comme paramètre.
Connection con = DriverManager.getConnection(...);
  Data d = DataFactory.getData(con);

// Exécutez l'analyse et créez un itérateur pour les lignes 11 à 20
  Iterator<EmployeeBean> employees = d.query("select * from employee where workdept = ?1.departmentNumber",
         theDepartment, new IteratorPagingResultHandler(EmployeeBean.class,11, 20));

Commentaires