マッパークラスは、SQLマッパーを定義する時に指定しますが、どのマッパークラスを指定するかによりデータベースアクセス時の振る舞いが変わってきます。
Webtribeではいくつかのマッパークラスを標準で提供していますが、次のように、標準のマッパークラスでは実現できない処理を行う必要がある場合には、要件に応じたマッパークラスを作成し、プロジェクトに登録して使うことができます。
マッパークラスを作成するために必要なものは、次の通りです。
ここでは例として、テーブルから全レコードを削除するマッパークラスのコーディングについて説明します。
全レコードを削除するだけですので、入力アイテム、出力アイテムとも使いません。(絞込み条件や処理結果のデータが発生しないためです。)
マッパークラスに定義された内容を実行するだけの処理となります。
SQLマッパーに定義された SQL が
DELETE FROM WORKTABLEといった SQL になる場合、この SQL には入力パラメータ、出力パラメータのいずれも必要ありません。そこで、入力アイテム、出力アイテムの処理は行っていません。
補足1: package samples; 2: import java.sql.SQLException; 3: import java.sql.Statement; 4: import jp.ne.mki.wedge.run.db.dc.SqlDataControl; 5: import jp.ne.mki.wedge.run.interfaces.DataInterface; 6: import jp.ne.mki.wedge.run.interfaces.DcRequest; 7: 8: public class SimpleDeleteDc extends SqlDataControl { 9: 10: protected DataInterface[] executeSql(DcRequest req) throws SQLException { 11: int updatedRecordCount = 0; 12: Statement stmt = null; 13: 14: try { 15: stmt = req.createStatement(); 16: updatedRecordCount = stmt.executeUpdate(req.getSql()); 17: req.setUpdateErrorLine(0); 18: } catch (SQLException ex) { 19: req.setUpdateErrorLine(1); 20: throw ex; 21: } finally { 22: req.setUpdateTargetCount(0); 23: req.setDbAccessCount(1); 24: req.setDbUpdatedCount(updatedRecordCount); 25: 26: req.closeDbObject(stmt); 27: } 28: 29: return null; 30: } 31: }
補足
補足
補足
補足
補足
補足
次に入力アイテムを処理するマッパークラスのコーディングについて説明します。
ここでは例として、次のような
UPDATE WORKTABLE SET NAME=? WHERE ID=?といった、指定された条件に該当するレコードに対してだけ、値を更新する SQL を実行します。
1: package samples;
2: import java.io.IOException;
3: import java.sql.PreparedStatement;
4: import java.sql.SQLException;
5: import java.text.ParseException;
6: import jp.ne.mki.wedge.run.db.dc.SqlDataControl;
7: import jp.ne.mki.wedge.run.interfaces.DBDataConvertInterface;
8: import jp.ne.mki.wedge.run.interfaces.DataInterface;
9: import jp.ne.mki.wedge.run.interfaces.DcRequest;
10:
11: public class SimpleUpdateDc extends SqlDataControl {
12:
13: protected DataInterface[] executeSql(DcRequest req) throws SQLException, ParseException, IOException {
14: PreparedStatement stmt = null;
15: int colCount = req.getColumns();
16: int rowCount = req.getRows();
17: int updatedCount = 0;
18: int updatedRecordCount = 0;
19: int errorRowNo = 0;
20:
21: try {
22: DataInterface[] inItemArray = req.getInputRecordArray();
23: DBDataConvertInterface[] dbCvIn = req.getInDbCvClassArray();
24: stmt = req.prepareStatement();
25: // stmt = req.prepareStatement(req.getSql());
26:
27: for (int ii = 0; ii < rowCount; ii++) {
28: errorRowNo++;
29:
30: for (int jj = 0; jj < colCount; jj++) {
31: String data = inItemArray[jj].getString(ii);
32: if (dbCvIn[jj] instanceof DBDataConvert) {
33: ((DBDataConvert) dbCvIn[jj]).setObject(stmt, jj + 1, data);
34: } else {
35: dbCvIn[jj].setData(stmt, jj + 1, data);
36: }
37: }
38:
39: int count = stmt.executeUpdate();
40: if (count > 0) {
41: updatedCount++;
42: updatedRecordCount += count;
43: }
44: }
45: req.setUpdateErrorLine(0);
46: } catch (SQLException ex) {
47: req.setUpdateErrorLine(errorRowNo);
48: throw ex;
49: } finally {
50: req.setUpdateTargetCount(rowCount);
51: req.setDbAccessCount(updatedCount);
52: req.setDbUpdatedCount(updatedRecordCount);
53:
54: req.closeDbObject(stmt);
55: }
56:
57: return null;
58: }
59: }
req.prepareStatement(req.getSql());を実行するのと同じ動作になります。
次に、全件検索の SQL を例にとり、出力アイテムを使ったマッパークラスのコーディングについて説明します。
ここでは例として次のような SQL を実行します。
SELECT ID, NAME FROM WORKTABLEID, NAME という 2つのカラムが検索対象となっていますので、この 2つのカラムを出力アイテムにセットするためのコーディングが追加されています。
1: package samples;
2: import java.io.IOException;
3: import java.sql.ResultSet;
4: import java.sql.SQLException;
5: import java.sql.Statement;
6: import jp.ne.mki.wedge.run.db.dc.SqlDataControl;
7: import jp.ne.mki.wedge.run.interfaces.DBDataConvertInterface;
8: import jp.ne.mki.wedge.run.interfaces.DataInterface;
9: import jp.ne.mki.wedge.run.interfaces.DcRequest;
10:
11: public class SimpleQueryAllRecordsDC extends SqlDataControl {
12:
13: protected DataInterface[] executeSql(DcRequest req) throws SQLException, IOException {
14: DataInterface[] outItemArray = null;
15: int readRowCount = 0;
16: Statement stmt = null;
17: ResultSet rs = null;
18:
19: try {
20: stmt = req.createStatement();
21: rs = stmt.executeQuery(req.getSql());
22: int outColumnCount = rs.getMetaData().getColumnCount();
23: outItemArray = createOutputDataArray(outColumnCount);
24: DBDataConvertInterface[] dbCvOut = req.getOutDbCvClassArray();
25: while (rs.next()) {
26: for (int ii = 0; ii < outColumnCount; ii++) {
27: String data;
28: if (dbCvOut[ii] instanceof DBDataConvert) {
29: data = ((DBDataConvert) dbCvOut[ii]).getObject(rs, ii + 1);
30: } else {
31: data = dbCvOut[ii].getData(rs, ii + 1);
32: }
33: outItemArray[ii].addString(data);
34: }
35: readRowCount++;
36: }
37: } finally {
38: req.setDbAccessCount(readRowCount);
39: req.closeDbObject(rs);
40: req.closeDbObject(stmt);
41: }
42:
43: return outItemArray;
44: }
45: }
次に、絞込み条件付き検索の SQL を例にとり、入力アイテム出力アイテムを使ったマッパークラスのコーディングについて説明します。
ここでは例として次のような SQL を実行します。
SELECT NAME FROM WORKTABLE WHERE ID=?ここでは ID カラムに検索条件を設定し、NAME カラムのデータを検索しますので、マッパークラスは、入力アイテムをセットし、出力アイテムを受け取る処理を行います。
1: package samples;
2: import java.io.IOException;
3: import java.sql.PreparedStatement;
4: import java.sql.ResultSet;
5: import java.sql.SQLException;
6: import java.text.ParseException;
7: import jp.ne.mki.wedge.run.db.dc.SqlDataControl;
8: import jp.ne.mki.wedge.run.interfaces.DBDataConvertInterface;
9: import jp.ne.mki.wedge.run.interfaces.DataInterface;
10: import jp.ne.mki.wedge.run.interfaces.DcRequest;
11:
12: public class SimpleQueryDC extends SqlDataControl {
13:
14: protected DataInterface[] executeSql(DcRequest req) throws SQLException, ParseException, IOException {
15:
16: int rowCount = req.getRows();
17: DataInterface[] outItemArray = null;
18: int readRowCount = 0;
19:
20: DataInterface[] inItemArray = req.getInputRecordArray();
21: PreparedStatement stmt = null;
22:
23: try {
24: int colCount = req.getColumns();
25: DBDataConvertInterface[] dbCvIn = req.getInDbCvClassArray();
26: DBDataConvertInterface[] dbCvOut = req.getOutDbCvClassArray();
27: stmt = req.prepareStatement();
28:
29: for (int ii = 0; ii < rowCount; ii++) {
30: for (int jj = 0; jj < colCount; jj++) {
31: String data = inItemArray[jj].getString(ii);
32: if (dbCvIn[jj] instanceof DBDataConvert) {
33: ((DBDataConvert) dbCvIn[jj]).setObject(stmt, jj + 1, data);
34: } else {
35: dbCvIn[jj].setData(stmt, jj + 1, data);
36: }
37: }
38:
39: ResultSet rs = null;
40:
41: try {
42: rs = stmt.executeQuery();
43: int outColumnCount = rs.getMetaData().getColumnCount();
44: if (outItemArray == null) {
45: outItemArray = createOutputDataArray(outColumnCount);
46: }
47:
48: while (rs.next()) {
49: for (int jj = 0; jj < outColumnCount; jj++) {
50: String data;
51: if (dbCvOut[jj] instanceof DBDataConvert) {
52: data = ((DBDataConvert) dbCvOut[jj]).getObject(rs, jj + 1);
53: } else {
54: data = dbCvOut[jj].getData(rs, jj + 1);
55: }
56: outItemArray[jj].addString(data);
57: }
58: readRowCount++;
59: }
60: } finally {
61: req.closeDbObject(rs);
62: }
63: }
64: } finally {
65: req.setDbAccessCount(readRowCount);
66: req.closeDbObject(stmt);
67: }
68:
69: return outItemArray;
70: }
71: }
ここでは表タイプを使って、PL/SQL に配列を渡し、結果も配列で受け取るためのサンプルについて説明します。
注意
Example...create or replace type StringList as table of varchar2(16);16桁の可変文字列を要素として保持する表タイプを、「StringList」という名称で定義します。
create or replace package array as
procedure ReverseStringList(InputString in StringList, OutputString out StringList);
end array;
表タイプ「StringList」を入力項目、出力項目として受け渡しするプロシージャを パッケージ「array」に「ReverseStringList」という名称で定義します。
create or replace package body array as
procedure ReverseStringList(InputString in StringList, OutputString out StringList) as
ListCount number(3);
ii number(3);
idx number(3);
begin
ListCount := InputString.count;
OutputString := StringList();
OutputString.extend(ListCount);
idx := ListCount;
FOR ii IN 1..ListCount LOOP
OutputString(ii) := InputString(idx);
idx := idx - 1;
END LOOP;
end ReverseStringList;
end array;
受け取った可変文字列の配列を、逆の順番に並び替えて呼び出し元に返すプロシージャを定義します。
1: package samples;
2: import java.sql.Array;
3: import java.sql.CallableStatement;
4: import java.sql.SQLException;
5: import java.sql.Types;
6:
7: import oracle.sql.ARRAY;
8: import oracle.sql.ArrayDescriptor;
9: import jp.ne.mki.wedge.run.db.dc.SqlDataControl;
10: import jp.ne.mki.wedge.run.interfaces.DataInterface;
11: import jp.ne.mki.wedge.run.interfaces.DcRequest;
12:
13: public class SimpleSpDC extends SqlDataControl {
14: private final static String TABLE_TYPE_NAME = "STRINGLIST";
15: private final static String SQL = "{call array.ReverseStringList(?,?)}";
16:
17: protected DataInterface[] executeSql(DcRequest req) throws SQLException {
18: CallableStatement stmt = null;
19: DataInterface[] inItemArray = req.getInputRecordArray();
20: String[] inStringArray = null;
21: DataInterface[] outItemArray = null;
22:
23: try {
24: int itemSize = inItemArray[0].getSize();
25: inStringArray = new String[itemSize];
26: for (int ii = 0; ii < itemSize; ii++) {
27: String data = inItemArray[0].getString(ii);
28: inStringArray[ii] = data;
29: }
30:
31: stmt = req.prepareCall(SQL);
32: ArrayDescriptor desc = ArrayDescriptor.createDescriptor(TABLE_TYPE_NAME, stmt.getConnection());
33: ARRAY arrayIn = new ARRAY(desc, stmt.getConnection(), inStringArray);
34: stmt.setArray(1, arrayIn);
35: stmt.registerOutParameter(2, Types.ARRAY, TABLE_TYPE_NAME);
36: stmt.execute();
37:
38: Array arrayOut = stmt.getArray(2);
39: String[] stringArray = (String[]) arrayOut.getArray();
40: outItemArray = createOutputDataArray(1);
41: int outSize = stringArray.length;
42: DataInterface di = outItemArray[0];
43: for (int ii = 0; ii < outSize; ii++) {
44: di.addString(stringArray[ii]);
45: }
46: } finally {
47: req.closeDbObject(stmt);
48: }
49:
50: return outItemArray;
51: }
52: }
実装したマッパークラスを使うためには、いくつかの設定が必要となります。
ここでは、SimpleQueryDC を使う場合の手順について説明します。
まずマッパークラスのソースをコンパイルして class ファイルを生成します。
コンパイルを行うには、IDE(統合開発環境)を使う方法と、JDK を使う方法がありますが、IDE の場合は、IDE のツールによって設定が異なりますので、ここでは JDK を使ってコンパイルを行う方法について説明します。
コンパイルを行うには、CLASSPATH に wedge-common-1.4.0.jar, wedge-common-server-1.4.0.jar, wedge-optional-1.4.0.jar, wedge-run-common-1.4.0.jar, wedge-run-data-1.4.0.jar, wedge-run-server-1.4.0.jar を設定します。
Example...set JAVA_HOME=c:\jdk1.7.0_13 set PATH=%JAVA_HOME%\bin;%PATH% set CLASSPATH=c:\Tomcat6.0\webapps\webtribe\WEB-INF\lib\wedge-common-1.4.0.jar;\WEB-INF\lib\wedge-common-server-1.4.0.jar;\WEB-INF\lib\wedge-optional-1.4.0.jar;\WEB-INF\lib\wedge-run-common-1.4.0.jar;\WEB-INF\lib\wedge-run-data-1.4.0.jar;\WEB-INF\lib\wedge-run-server-1.4.0.jar javac SimpleQueryDC.javaコンパイルが通ると、SimpleQueryDC.class というファイルが作成されます。


| 論理名 | シンプルクエリDC |
| 物理名 | SimpleQueryDC |
| クラス名 | samples.SimpleQueryDC |

補足
create table worktable (
id number(7) not null,
name varchar2(16),
version varchar2(16)
);
alter table worktable add constraint pk_worktable primary key (id);
insert into worktable values(1,'Sparkler','1.1.4');
insert into worktable values(2,'Pumpkin','1.1.5');
insert into worktable values(3,'Abigail','1.1.6');
insert into worktable values(4,'Brutus','1.1.7');
insert into worktable values(5,'Chelsea','1.1.8');
insert into worktable values(6,'Playground','1.2');
insert into worktable values(7,'Cricket','1.2.2');
insert into worktable values(8,'Kestrel','1.3');
insert into worktable values(9,'Ladybird','1.3.1');
insert into worktable values(10,'Merlin','1.4.0');
insert into worktable values(11,'Hopper','1.6.0');
insert into worktable values(12,'Mantis','1.4.2');
insert into worktable values(13,'Tiger','1.5.0');
insert into worktable values(14,'DragonFly','1.5.1');
insert into worktable values(15,'Mustang','1.6.0');
commit;
コンパイルしたマッパークラスのクラスファイル(SimpleQueryDC.class)をコピーします。
Example...md c:\Tomcat6.0\webapps\webtribe\WEB-INF\classes md c:\Tomcat6.0\webapps\webtribe\WEB-INF\classes\samples copy SimpleQueryDC.class c:\Tomcat6.0\webapps\webtribe\WEB-INF\classes\samplesLinux の場合
mkdir -p /opt/jakarta-tomcat-6.0/webapps/webtribe/WEB-INF/classes/samples cp SimpleQueryDC.class /opt/jakarta-tomcat-6.0/webapps/webtribe/WEB-INF/classes/samples
classes ディレクトリを CLASSPATH に追加します。
(変更前) set CLASSPATH=%JARFILE_CORE%;%RUNJDBC%
(変更後) set CLASSPATH=classes;%JARFILE_CORE%;%RUNJDBC%
(変更前) CLASSPATH=%JARFILE_CORE%;%RUNJDBC%
(変更後) CLASSPATH=classes;%JARFILE_CORE%;%RUNJDBC%
(変更前) set CLASSPATH=${JARFILE_CORE}:${RUNJDBC}
(変更後) set CLASSPATH=classes:${JARFILE_CORE}:${RUNJDBC}
DBServerを再起動し、CLASSPATH の設定を有効にします。
トランザクションテスト等で作成したSQLマッパーを実行し、動作を確認します。
トレースログで、作成したSQLマッパーが呼び出されているかどうか確認することができます。
●図7. [トランザクションテスト]
[トレースログ]
[2004/05/10 19:49:51]
*DC Class
[samples.SimpleQueryDC]
*SQL
[SELECT NAME FROM WORKTABLE WHERE ID = ? ]
*Input DB convert class
[]
*Input data
[12]
*Output DB convert class
[]
*Output data
[Mantis]