Transmission de valeurs des structures de données dans les instructions SQL

pureQuery contient les règles par défaut concernant l'utilisation de paramètres que vous transmettez aux méthodes annotées ou intégrées sous forme de valeurs pour les paramètres des instructions SQL. pureQuery contient également les règles par défaut concernant l'utilisation de paramètres transmis lors de l'enregistrement de paramètres OUT et INOUT. Lorsque vous utilisez des méthodes annotées, vous pouvez écraser ces règles par défaut avec une implémentation de l'interface ParameterHandler<T>.

L'interface ParameterHandler<T> comprend une seule méthode : handleParameters(). Lorsque pureQuery appelle cette méthode, elle transmet un objet PreparedStatement utilisé pour exécuter l'instruction SQL avec les paramètres que vous avez transmis à la méthode annotée.

Utilisez les objets ParameterHandler<T> pour définir les valeurs des paramètres dans l'instruction SQL et pour enregistrer tous les paramètres OUT ou INOUT. Pour plus d'informations sur l'interface java.sql.PreparedStatement, voir Javadoc pour votre SDK Java.

Exemple 1

L'objectif de cet exemple est décrit dans les commentaires du code.

package com.samplePackage;

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Types;

import com.ibm.pdq.runtime.generator.ParameterHandler;

// Ceci est un exemple d'un ParameterHandler personnalisé qui :
// (1) valide un paramètre de méthode et 
// (2) traite un paramètre de méthode
// avant de définir le paramètre de méthode comme un paramètre d'instruction.  Ce
// ParameterHandler personnalisé
// (3) définit également l'un des paramètres de l'instruction avec une valeur figée dans le code.
//
// Ce premier paramètre d'instruction est bonusFactor.  La valeur définie est un nombre compris entre
// 1 et 2.  La valeur transmise sous forme de paramètre de méthode est comprise entre 100 % et 200 %.
// C'est pourquoi le gestionnaire de paramètres vérifie que la valeur transmise est bien comprise entre
// 100 et 200 et il divise la valeur par 100 avant de la paramétrer comme le paramètre d'instruction
// bonusFactor.
//
// Le deuxième paramètre d'instruction est bonusMaxSumForDept.  Il est défini avec une valeur
// figée dans le code dans le gestionnaire de paramètres -- 20 000,00 $.
public class BonusIncreaseParameterHandler implements ParameterHandler
{
  // ?1 est la valeur de renvoi
  // Le paramètre IN ?2 est défini à partir du paramètre de méthode transmis newBonusPercentageOfOldBonus
  // Le paramètre IN ?3 est défini à partir d'un nombre fixe dans ParameterHandler
  // Il y a quatre paramètres OUT dans l'instruction d'appel SQL :
  // (1) ?4 => deptsWithoutNewBonuses
  // (2) ?5 => countDeptsViewed
  // (3) ?6 => countDeptsBonusChanged
  // (5) ?7 => errorMsg
  public void handleParameters (PreparedStatement stmt, Object... parameters) throws SQLException
  {
    CallableStatement cstmt = (CallableStatement) stmt;
    
    double newBonusPercentageOfOldBonus = (Double) parameters[1];

    // Vérifiez que la valeur du paramètre est raisonnable
    if (100 > newBonusPercentageOfOldBonus || 200 < newBonusPercentageOfOldBonus) { throw new RuntimeException (
      "bonusFactorPercentage doit être compris entre 100 et 200 inclus.  Le nouveau bonus correspond à ce pourcentage de l'ancien bonus.  (Ainsi, par exemple, si bonusFactorPercentage=100, le bonus ne change pas.)"); }

    // Calculez le paramètre bonusFactor à définir dans cstmt
    double bonusFactor = newBonusPercentageOfOldBonus / 100.0;
    
    // La valeur de ce paramètre cstmt est fixe
    double bonusMaxSumForDept = 20000.00;
    
    // Enregistrez les paramètres OUT et définissez les paramètres IN
    cstmt.registerOutParameter (1, Types.INTEGER);
    stmt.setDouble (2, bonusFactor);
    stmt.setDouble (3, bonusMaxSumForDept);
    cstmt.registerOutParameter (4, Types.VARCHAR);
    cstmt.registerOutParameter (5, Types.INTEGER);
    cstmt.registerOutParameter (6, Types.INTEGER);
    cstmt.registerOutParameter (7, Types.VARCHAR);
  }

}

Exemple 2

L'objectif de cet exemple est décrit dans les commentaires du code.

package com.samplePackage;

import java.sql.PreparedStatement;
import java.sql.SQLException;

import com.ibm.pdq.runtime.generator.ParameterHandler;

// Ceci est un exemple d'un ParameterHandler personnalisé qui active un bean d'utilisateur
// "legacy" à utiliser sous sa forme inchangée.  Reportez-vous à la classe CustomDepartment pour plus d'informations
// sur l'implémentation du bean et pour savoir pourquoi elle est utilisée sous sa forme inchangée.
public class CustomDepartmentParameterHandler implements ParameterHandler
{

  public void handleParameters (PreparedStatement stmt, Object... parameters) throws SQLException
  {
    CustomDepartment department = (CustomDepartment) parameters[0];
    stmt.setString (1, department.getDepartmentCode ()); 
  }

}

Voici la définition du bean CustomDepartment.

package com.samplePackage;

// Ceci est un exemple d'un bean "legacy" qu'un utilisateur théorique peut ne pas vouloir
// modifier. Modifications qu'il doit apporter pour rendre ce bean conforme :
// (1) Changer les noms de propriétés, ajouter @Column ou ajouter @ColumnOverride pour
// activer les propriétés à mapper vers les colonnes.
// (2) Ajouter des méthodes de réglage correspondant aux méthodes d'obtention incluses.
//
// Le changement (1) est une modification simple -- mais si l'utilisateur possède un grand nombre de beans
// identiques ou s'il possède un code légal qu'il ne peut pas modifier, il peut alors utiliser
// ParameterHandler à la place.
//
// Le changement (2) peut éventuellement nécessiter d'importants changements à
// l'architecture de conception de l'utilisateur. Par exemple, dans ce cas particulier, il se peut que l'utilisateur
// souhaite seulement autoriser des changements sur departmentName et departmentCode lorsque les deux
// sont modifiés ensemble. C'est pourquoi il dispose d'une méthode changeDepartment(String,String),
// mais d'aucune méthode setDepartmentName(String) ou setDepartmentCode(String).  Un
// ParameterHandler personnalisé permet à l'utilisateur de continuer à utiliser ce bean tel quel.
public class CustomDepartment
{
  private String departmentName;
  private String departmentCode;
  // Autres propriétés

  public CustomDepartment (String departmentName, String departmentCode)
  {
    this.departmentName = departmentName;
    this.departmentCode = departmentCode;
  }
  
  public void changeDepartment (String departmentName, String departmentCode)
  {
    this.departmentName = departmentName;
    this.departmentCode = departmentCode;
  }

  public String getDepartmentName ()
  {
    return departmentName;
  }

  public String getDepartmentCode ()
  {
    return departmentCode;
  }

  // Autres méthodes
}

Exemple 3

L'objectif de cet exemple est décrit dans les commentaires du code.

package com.samplePackage;

import java.sql.PreparedStatement;
import java.sql.SQLException;

import com.ibm.pdq.runtime.generator.ParameterHandler;

// Ceci est un exemple d'un gestionnaire de paramètres personnalisé dans lequel les paramètres SQL
// ne sont pas définis en fonction des valeurs déjà disponibles dans les paramètres de méthode.  Dans
// ce cas, le longueur du projet est calculée en multipliant une valeur d'une propriété 
// du paramètre ProjectLevel par une valeur d'une propriété du paramètre
// AdefUser.
public class ProjectLevelParameterHandler implements ParameterHandler
{
  public void handleParameters (PreparedStatement stmt, Object... parameters) throws SQLException
  {
    System.out.println("CDS in parameter handler");
    ProjectLevel projectLevel = (ProjectLevel) parameters[0];
    AdefUser adefUser = (AdefUser) parameters[1];
    
    int numberOfEmployees = adefUser.getNumberOfEmloyees ();
    double lengthInDays = projectLevel.getMinimumProjectLengthInDaysPerDepartmentMember () * numberOfEmployees;
    String workDepartment = adefUser.getWorkDept ();
    
    System.out.println("CDS trying to set parameters");
    stmt.setDouble (1, numberOfEmployees);
    stmt.setDouble (2, lengthInDays);
    stmt.setString (3, workDepartment);
  }
}

Voici la définition du bean AdefUser.

package com.samplePackage;

import com.ibm.pdq.annotation.Column;

public class AdefUser
{
  private String workDept;
  private int numberOfEmloyees;
  
  public AdefUser (String workDept, int numberOfEmployees)
  {
    this.workDept = workDept;
    this.numberOfEmloyees = numberOfEmployees;
  }
  
  @Column(name="no_of_employees")
  public int getNumberOfEmloyees ()
  {
    return numberOfEmloyees;
  }
  
  public void setNumberOfEmloyees (int numberOfEmloyees)
  {
    this.numberOfEmloyees = numberOfEmloyees;
  }
  
  public String getWorkDept ()
  {
    return workDept;
  }
  
  public void setWorkDept (String workDept)
  {
    this.workDept = workDept;
  }
}

Voici la définition du bean ProjectLevel.

package com.samplePackage;


public class ProjectLevel
{
  private int projectLevel;
  private double minimumProjectLengthInDaysPerDepartmentMember;
  
  public ProjectLevel(int projectLevel, double minimumProjectLengthInDaysPerDepartmentMember)
  {
    this.projectLevel = projectLevel;
    this.minimumProjectLengthInDaysPerDepartmentMember = minimumProjectLengthInDaysPerDepartmentMember;
  }

  public double getMinimumProjectLengthInDaysPerDepartmentMember ()
  {
    return minimumProjectLengthInDaysPerDepartmentMember;
  }

  public void setMinimumProjectLengthInDaysPerDepartmentMember (double minimumProjectLengthInDaysPerDepartmentMember)
  {
    this.minimumProjectLengthInDaysPerDepartmentMember = minimumProjectLengthInDaysPerDepartmentMember;
  }

  public int getProjectLevel ()
  {
    return projectLevel;
  }

  public void setProjectLevel (int projectLevel)
  {
    this.projectLevel = projectLevel;
  }

}

Commentaires