ParameterHandler<T> インターフェースにあるメソッドは、handleParameters() だけです。pureQuery がこのメソッドを呼び出すと、アノテーション付きメソッドに渡されたパラメーターと一緒に、SQL ステートメントの実行に使用された PreparedStatement オブジェクトを渡します。
ParameterHandler<T> オブジェクトを使用して、SQL ステートメントにおけるパラメーターの値を設定し、任意の OUT パラメーターまたは INOUT パラメーターを登録します。 java.sql.PreparedStatement インターフェースについては、ご使用の Java SDK の Javadoc を参照してください。
この例の目的については、コード内のコメントで説明されています。
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;
// これはカスタム ParameterHandler の例です。この例では、
// メソッド・パラメーターをステートメント・パラメーターとして設定する前に、
// (1) メソッド・パラメーターを検証し、
// (2) メソッド・パラメーターを処理します。// また、このカスタム ParameterHandler は、
// (3) ステートメント・パラメーターの 1 つにハードコーディング値を設定します。
//
// 最初のステートメント・パラメーターは bonusFactor です。// 設定値は、1 から 2 までの間の数値です。
// メソッド・パラメーターとして渡される値は、100% から 200% までの値です。
// そのため、パラメーター・ハンドラーは、渡された値が
// 100 から 200 までの値であることを検証し、100 で値を除算してから、
// その値をステートメント・パラメーター bonusFactor として設定します。
//
// 2 番目のステートメント・パラメーターは bonusMaxSumForDept です。これは、
// パラメーター・ハンドラーでハードコーディングされた値 ($20,000.00) に設定されます。
public class BonusIncreaseParameterHandler implements ParameterHandler
{
// ?1 が戻り値です。
// IN パラメーター ?2 は、渡されたメソッド・パラメーター newBonusPercentageOfOldBonus から設定されます。
// IN パラメーター ?3 は、ParameterHandler の固定数値から設定されます。
// この SQL の CALL ステートメントには OUT パラメーターが以下のように 4 つあります。
// (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];
// パラメーターの値が妥当であることを検証します。
if (100 > newBonusPercentageOfOldBonus || 200 < newBonusPercentageOfOldBonus) { throw new RuntimeException (
"The bonusFactorPercentage must be between 100 and 200 inclusive. The new bonus will be this percentage of the old bonus. (So, for example, if bonusFactorPercentage=100, then the bonus will not change.)"); }
// cstmt に設定する bonusFactor を計算します。
double bonusFactor = newBonusPercentageOfOldBonus / 100.0;
// この cstmt パラメーターは固定値です。
double bonusMaxSumForDept = 20000.00;
// OUT パラメーターを登録し、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);
}
}
この例の目的については、コード内のコメントで説明されています。
package com.samplePackage;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import com.ibm.pdq.runtime.generator.ParameterHandler;
// これは、「レガシー」ユーザー Bean を未変更のまま使用できるようにする、
// カスタム ParameterHandler の例です。Bean インプリメンテーションについて、および
// 未変更のまま使用する理由について詳しくは、CustomDepartment クラスを参照してください。
public class CustomDepartmentParameterHandler implements ParameterHandler
{
public void handleParameters (PreparedStatement stmt, Object... parameters) throws SQLException
{
CustomDepartment department = (CustomDepartment) parameters[0];
stmt.setString (1, department.getDepartmentCode ());
}
}
以下に、CustomDepartment Bean の定義を記します。
package com.samplePackage;
// これは、理論上のユーザーが変更を加えない可能性のある「レガシー」Bean の例です。
// 変更を加える必要がある場合には、以下の Bean に対応するようにしてください。
// (1) プロパティー名を変更する、@Column を追加する、または @ColumnOverride を追加する、
// このいずれかを行い、プロパティーを列にマップできるようにします。
// (2) 組み込まれている getter に対応する setter を追加します。
//
// 変更 (1) は簡単な修正です。ただし、ユーザーが以下のようにたくさんの Bean
// を持っているか、変更できないレガシー・コードがある場合には、
// 代わりに ParameterHandler を使用できます。
//
// 変更 (2) の場合には、ユーザーの設計アーキテクチャーにかなりの変更が求められる
// 可能性があります。例えば、このようなケースでは、departmentName と departmentCode の
// 両方が一緒に変更される場合にのみ、ユーザーがこれらに対する変更を許可することが
// あります。そのために、changeDepartment(String,String) メソッドはありますが、
// setDepartmentName(String) メソッドまたは setDepartmentCode(String) メソッドはありません。
// カスタム ParameterHandler では、ユーザーはこの Bean を現状のまま使用することができます。
public class CustomDepartment
{
private String departmentName;
private String departmentCode;
// 他のプロパティー
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;
}
// 他のメソッド
}
この例の目的については、コード内のコメントで説明されています。
package com.samplePackage;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import com.ibm.pdq.runtime.generator.ParameterHandler;
// これは、メソッド・パラメーターにおいて既に使用可能な値に基づいて SQL パラメーターが
// 設定されているのではないカスタム・パラメーター・ハンドラーの例です。この場合、
// プロジェクト長は ProjectLevel パラメーターのプロパティー値に 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);
}
}
以下に、AdefUser Bean の定義を記します。
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;
}
}
以下に、ProjectLevel Bean の定義を記します。
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;
}
}