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; } }