001/* 002 * Copyright (c) 2009 The openGion Project. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 013 * either express or implied. See the License for the specific language 014 * governing permissions and limitations under the License. 015 */ 016package org.opengion.fukurou.business; 017 018import java.sql.Connection; 019import java.sql.ParameterMetaData; 020import java.sql.PreparedStatement; 021import java.sql.ResultSet; 022import java.sql.ResultSetMetaData; 023import java.sql.SQLException; 024import java.util.HashMap; 025import java.util.Locale; 026import java.util.Map; 027import java.util.Set; 028import java.util.Arrays; 029 030import org.opengion.fukurou.db.ConnectionFactory; 031import org.opengion.fukurou.db.DBFunctionName; 032import org.opengion.fukurou.db.DBUtil; 033import org.opengion.fukurou.db.Transaction; 034import org.opengion.fukurou.model.Formatter; 035import org.opengion.fukurou.util.Closer; 036import org.opengion.fukurou.util.ErrMsg; 037import org.opengion.fukurou.util.ErrorMessage; 038import org.opengion.fukurou.util.HybsLoader; 039import org.opengion.fukurou.util.StringUtil; 040import org.opengion.fukurou.util.SystemParameter; 041import org.opengion.fukurou.util.HybsDateUtil; 042 043/** 044 * 業務ロジックを処理するために必要な共通メソッドの実行を行っている抽象クラスです。 045 * 046 * メインロジックについては、各サブクラスで実装する必要があります。 047 * 048 * @og.rev 5.1.1.0 (2009/12/01) 新規作成 049 * @og.group 業務ロジック 050 * 051 * @version 5.0 052 * @author Hiroki Nakamura 053 * @since JDK1.6, 054 */ 055public abstract class AbstractBizLogic { 056 private static final String CR = System.getProperty("line.separator"); 057 058 /** エラーメッセージをセットする際に使用します {@value} */ 059 protected static final int OK = ErrorMessage.OK; 060 /** エラーメッセージをセットする際に使用します {@value} */ 061 protected static final int WARNING = ErrorMessage.WARNING; 062 /** エラーメッセージをセットする際に使用します {@value} */ 063 protected static final int NG = ErrorMessage.NG; 064 /** エラーメッセージをセットする際に使用します {@value} */ 065 protected static final int EXCEPTION = ErrorMessage.EXCEPTION; 066 /** エラーメッセージをセットする際に使用します {@value} */ 067 protected static final int ORCL_ERR = ErrorMessage.ORCL_ERR; 068 069 private Connection conn = null; 070 private Transaction tran = null; // 5.1.9.0 (2010/08/01) シーケンス対応 071 private String dbid = null; // 5.1.9.0 (2010/08/01) シーケンス対応 072 DBFunctionName dbName = null; // 5.1.9.0 (2010/08/01) シーケンス対応 073 private HybsLoader loader = null; 074 private String[] keys = null; 075 private String[] vals = null; 076 private final StringBuilder paramKeysStr = new StringBuilder( "|" ); 077 private final Map<String, String> variableMap = new HashMap<String, String>(); 078 private final Map<String, Formatter> formatMap = new HashMap<String, Formatter>(); 079 private final Map<String, SystemParameter> sysParamMap = new HashMap<String, SystemParameter>(); 080 private final ErrorMessage errMsg = new ErrorMessage(); 081 private String bizRtn = null; // 5.1.8.0 (2010/07/01) メソッド名と変数名を分ける。 082 private boolean debugFlag = false; // 5.1.8.0 (2010/07/01) メソッド名と変数名を分ける。 083 084 private final StringBuilder debugMsg = new StringBuilder(); 085 private boolean useParamMetaData = false; // 5.3.8.0 (2011/08/01) useParamMetaData を ConnectionFactory経由で取得。(PostgreSQL対応) 086 087 /** 088 * 配列側テーブルモデル 089 * 090 * 配列型テーブルモデル自体は、protected属性であるため、サブクラスから直接参照することができます。 091 * 但し、これは、各業務ロジックで直接参照することを想定したものではなく、BizLogicの 092 * メイン構造を拡張するサブクラスを定義する際に使用することを想定しています。 093 * (この想定がなければ、本来は、package privateにすべきです) 094 * このため、業務ロジックを各実装クラスでは直接参照しないで下さい。 095 */ 096 protected ArrayTableModel table = null; 097 098 /** 099 * 配列型テーブルモデルの現在の処理行 100 * 101 * 行番号自体は、protected属性であるため、サブクラスから直接参照することができます。 102 * 但し、これは、各業務ロジックで直接参照することを想定したものではなく、BizLogicの 103 * メイン構造を拡張するサブクラスを定義する際に使用することを想定しています。 104 * (この想定がなければ、本来は、package privateにすべきです) 105 * このため、業務ロジックを各実装クラスでは直接参照しないで下さい。 106 * 107 * ※ インデックス(row)とは、このArrayTableModel に持つ vals 配列の行のインデックスです。 108 * よって、オリジナルのDBTableModelの行番号ではありません。 109 */ 110 protected int row = -1; 111 112 /** 113 * DBのトランザクションオブジェクトを指定します。 114 * 各実装クラスでは、コネクションのcommit,rollbackは行われません。 115 * (全てのDB処理は、1つのトランザクションとして処理されます。) 116 * このため、commit,rollbackは呼び出し元で行う必要があります。 117 * このメソッドは、1度しかセットすることができません。2回以上呼び出しするとエラーになります。 118 * 119 * @og.rev 5.1.9.0 (2010/08/01) 新規作成 120 * @og.rev 5.3.8.0 (2011/08/01) useParamMetaData を ConnectionFactory経由で取得。(PostgreSQL対応) 121 * 122 * @param tr トランザクション 123 */ 124 public void setTransaction( final Transaction tr ) { 125 tran = tr; 126 conn = tran.getConnection( dbid ); 127 useParamMetaData = ConnectionFactory.useParameterMetaData( dbid ); // 5.3.8.0 (2011/08/01) 128 } 129 130 /** 131 * 接続先IDを指定します。 132 * このメソッドは、1度しかセットすることができません。2回以上呼び出しするとエラーになります。 133 * 134 * @og.rev 5.1.9.0 (2010/08/01) 新規作成 135 * 136 * @param id 接続先ID 137 */ 138 void setDbid( final String id ) { 139 dbid = id; 140 } 141 142 /** 143 * 業務ロジックのクラスをロードするためのクラスローダーをセットします。 144 * このメソッドは、1度しかセットすることができません。2回以上呼び出しするとエラーになります。 145 * 146 * @og.rev 5.6.7.0 (2013/07/27) Exception を throw するとき、一旦、errMsg 変数にセットします。 147 * 148 * @param ldr クラスローダー 149 */ 150 void setLoader( final HybsLoader ldr ) { 151 if( loader != null ) { 152 // 5.6.7.0 (2013/07/27) Exception を throw するとき、一旦、errMsg 変数にセットします。 153 String errMsg = "既にクラスローダーがセットされています。" ; 154 throw new RuntimeException( errMsg ); 155 } 156 loader = ldr; 157 } 158 159 /** 160 * 配列型テーブルモデルをセットします。 161 * このメソッドは、1度しかセットすることができません。2回以上呼び出しするとエラーになります。 162 * 163 * @og.rev 5.6.7.0 (2013/07/27) Exception を throw するとき、一旦、errMsg 変数にセットします。 164 * 165 * @param tbl 配列型テーブルモデル 166 */ 167 void setTable( final ArrayTableModel tbl ) { 168 if( table != null ) { 169 // 5.6.7.0 (2013/07/27) Exception を throw するとき、一旦、errMsg 変数にセットします。 170 String errMsg = "既に配列型テーブルモデルがセットされています。" ; 171 throw new RuntimeException( errMsg ); 172 } 173 table = tbl; 174 } 175 176 /** 177 * 固定値のキーをCSV形式で指定します。 178 * このメソッドは、1度しかセットすることができません。2回以上呼び出しするとエラーになります。 179 * 180 * @og.rev 5.6.7.0 (2013/07/27) Exception を throw するとき、一旦、errMsg 変数にセットします。 181 * 182 * @param ks キー 183 */ 184 void setKeys( final String[] ks ) { 185 if( keys != null ) { 186 // 5.6.7.0 (2013/07/27) Exception を throw するとき、一旦、errMsg 変数にセットします。 187 String errMsg = "既に固定値配列(キー)がセットされています。" + CR 188 + " KESY =" + Arrays.toString( keys ) + CR 189 + " in keys=" + Arrays.toString( ks ) ; 190 throw new RuntimeException( errMsg ); 191 } 192 keys = ks; 193 } 194 195 /** 196 * 固定値の値をCSV形式で指定します。 197 * このメソッドは、1度しかセットすることができません。2回以上呼び出しするとエラーになります。 198 * 199 * @og.rev 5.6.7.0 (2013/07/27) Exception を throw するとき、一旦、errMsg 変数にセットします。 200 * 201 * @param vs 値 202 */ 203 void setVals( final String[] vs ) { 204 if( vals != null ) { 205 // 5.6.7.0 (2013/07/27) Exception を throw するとき、一旦、errMsg 変数にセットします。 206 String errMsg = "既に固定値配列(値)がセットされています。" + CR 207 + " VALS =" + Arrays.toString( vals ) + CR 208 + " in vals=" + Arrays.toString( vs ) ; 209 throw new RuntimeException( errMsg ); 210 } 211 vals = vs; 212 } 213 214 /** 215 * この処理の実行ユーザーIDを指定します。 216 * 217 * @param id 実行ユーザーID 218 */ 219 void setUserId( final String id ) { 220 variableMap.put( "CON.USERID", id); 221 } 222 223 /** 224 * 親(呼び出し)PGIDを指定します。 225 * 226 * @param id 親PGID 227 */ 228 void setParentPgId( final String id ) { 229 variableMap.put( "CON.PGPID", id ); 230 } 231 232 /** 233 * デバッグモードにします。 234 */ 235 void setDebug() { 236 debugFlag = true; 237 } 238 239 /** 240 * デバッグメッセージを取得します。 241 * 242 * @return デバッグメッセージ 243 */ 244 String getDebugMsg() { 245 return debugMsg.toString(); 246 } 247 248 /** 249 * 処理を実行します。 250 * 処理の方法は、main()メソッドにより定義されます。 251 * 実装クラスで発生した全ての例外は、Throwableオブジェクトとしてスローされます。 252 * 呼び出し元では、例外を確実にcatchして、commit,rollbackを行ってください。 253 * 254 * @og.rev 5.1.9.0 (2010/08/01) シーケンス対応 255 * 256 * @return 処理が成功したかどうか 257 * @throws Throwable 実行時の全エラーを上位に転送します。 258 */ 259 boolean exec() throws Throwable { 260 dbName = DBFunctionName.getDBName( ConnectionFactory.getDBName( dbid ) ); 261 makeParamMap(); 262 init(); 263 return main(); 264 } 265 266 /** 267 * 処理のメインロジックの前処理を記述します。 268 * 269 * このメソッド自体は、protected属性であるため、サブクラスから直接参照することができます。 270 * 但し、これは、各業務ロジックで直接参照することを想定したものではなく、BizLogicの 271 * メイン構造を拡張するサブクラスを定義する際に使用することを想定しています。 272 * (この想定がなければ、本来は、package privateにすべきです) 273 * このため、業務ロジックを各実装クラスでは直接参照しないで下さい。 274 */ 275 abstract protected void init(); 276 277 /** 278 * 処理のメインロジックを記述します。 279 * 280 * このメソッド自体は、protected属性であるため、サブクラスから直接参照することができます。 281 * 但し、これは、各業務ロジックで直接参照することを想定したものではなく、BizLogicの 282 * メイン構造を拡張するサブクラスを定義する際に使用することを想定しています。 283 * (この想定がなければ、本来は、package privateにすべきです) 284 * このため、業務ロジックを各実装クラスでは直接参照しないで下さい。 285 * 286 * @return 処理が正常終了したか 287 */ 288 abstract protected boolean main(); 289 290 /** 291 * 結果ステータスを返します。 292 * 293 * @return 結果ステータス 294 */ 295 int getKekka() { 296 return errMsg.getKekka(); 297 } 298 299 /** 300 * エラーメッセージオブジェクトを返します。 301 * 302 * @return エラーメッセージ 303 */ 304 ErrorMessage getErrMsg() { 305 return errMsg; 306 } 307 308 /** 309 * 業務ロジックの戻り値を返します。 310 * 311 * @return 戻り値 312 */ 313 String getReturn() { 314 return bizRtn; 315 } 316 317 /** 318 * 業務ロジックを実行するために、テーブルモデルが外部からセットされる必要があるか 319 * を返します。 320 * 必須である場合、その業務ロジックは、子ロジックとして呼び出すことができません。 321 * これは、子ロジック呼び出し時は、テーブルモデルがセットされないためです。 322 * (このクラスは、テーブルモデルが外部から指定されている必要はありません。) 323 * 324 * このメソッド自体は、protected属性であるため、サブクラスから直接参照することができます。 325 * 但し、これは、各業務ロジックで直接参照することを想定したものではなく、BizLogicの 326 * メイン構造を拡張するサブクラスを定義する際に使用することを想定しています。 327 * (この想定がなければ、本来は、package privateにすべきです) 328 * このため、業務ロジックを各実装クラスでは直接参照しないで下さい。 329 * 330 * @return テーブルモデルが外部からセットされる必要があるかどうか(常にfalse) 331 */ 332 protected boolean isRequireTable() { 333 return false; 334 } 335 336 /** 337 * デバッグモードかどうかを返します 338 * 339 * @return デバッグモードかどうか 340 */ 341 final protected boolean isDebug() { 342 return debugFlag; 343 } 344 345 /** 346 * デバッグメッセージを追加します。 347 * 348 * @param msg 追加するデバッグメッセージ 349 */ 350 final protected void debug( final String msg ) { 351 debugMsg.append( msg ).append( CR ); 352 } 353 354 /** 355 * 指定されたキーの値を返します。 356 * 357 * @param key キー 358 * 359 * @return 変数値 360 */ 361 final protected String var( final String key ) { 362 return variableMap.get( key ); 363 } 364 365 /** 366 * 指定されたキーの値をint型に変換して返します。 367 * 368 * @param key キー 369 * 370 * @return 変数値 371 */ 372 final protected int vari( final String key ) { 373 return var( key ) == null ? 0 : Integer.valueOf( var( key ) ); 374 } 375 376 /** 377 * 指定されたキーの値をdouble型に変換して返します。 378 * 379 * @param key キー 380 * 381 * @return 変数値 382 */ 383 final protected double vard( final String key ) { 384 return var( key ) == null ? 0.0 : Double.valueOf( var( key ) ); 385 } 386 387 /** 388 * パラメーターのキー一覧を配列形式で返します。 389 * このパラメーターは、業務ロジック内でセットされたパラメーターも含まれますのでご注意下さい。 390 * 391 * @return パラメーターのキー配列 392 */ 393 final protected String[] varKeys() { 394 Set<String> keys = variableMap.keySet(); 395 return keys.toArray( new String[keys.size()] ); 396 } 397 398 /** 399 * 指定されたキーで値を登録します。 400 * パラメーターとしてこの業務ロジックが呼ばれる際の引数となっている場合は、 401 * エラーとなります。 402 * 403 * @og.rev 5.2.1.0 (2010/10/01) チェックのバグを修正 404 * @og.rev 5.6.7.0 (2013/07/27) Exception を throw するとき、一旦、errMsg 変数にセットします。 405 * 406 * @param key キー 407 * @param val 値 408 */ 409 final protected void set( final String key, final String val ) { 410 if( paramKeysStr.indexOf( "|" + key + "|" ) >= 0 ) { 411 // 5.6.7.0 (2013/07/27) Exception を throw するとき、一旦、errMsg 変数にセットします。 412 String errMsg = "引数と同じ名前の変数を定義することはできません。" + CR 413 + " key =" + key + CR 414 + " 引数 =" + paramKeysStr ; 415 throw new RuntimeException( errMsg ); 416 } 417 variableMap.put( key, val ); 418 } 419 420 /** 421 * 指定されたキーで値を登録します。 422 * パラメーターとしてこの業務ロジックが呼ばれる際の引数となっている場合は、 423 * エラーとなります。 424 * 425 * @og.rev 5.1.9.0 (2010/08/01) 新規作成 426 * 427 * @param key キー 428 * @param val 値 429 */ 430 final protected void set( final String key, final int val ) { 431 set( key, String.valueOf( val ) ); 432 } 433 434 /** 435 * 指定されたキーで値(double型)を登録します。 436 * パラメーターとしてこの業務ロジックが呼ばれる際の引数となっている場合は、 437 * エラーとなります。 438 * 439 * @og.rev 5.1.9.0 (2010/08/01) 新規作成 440 * 441 * @param key キー 442 * @param val 値 443 */ 444 final protected void set( final String key, final double val ) { 445 set( key, String.valueOf( val ) ); 446 } 447 448 /** 449 * 処理中の行の指定されたキー(カラム名)の値を返します。 450 * 451 * @param key キー 452 * 453 * @return 値 454 */ 455 final protected String line( final String key ) { 456 return line( key, row ); 457 } 458 459 /** 460 * メインの配列型テーブルモデルに対して、行を指定して値を取得します。 461 * 指定された行が範囲を超えている場合は、nullを返します。 462 * 463 * @og.rev 5.1.8.0 (2010/07/01) テーブルに存在しないカラム名を指定した場合に、NullPointerExceptionが発生するバグを修正 464 * @og.rev 5.6.7.0 (2013/07/27) Exception を throw するとき、一旦、errMsg 変数にセットします。 465 * 466 * @param key キー 467 * @param rw 行番号(インデックス) 468 * 469 * @return 値 470 */ 471 final protected String line( final String key, final int rw ) { 472 if( table == null ) { 473 // 5.6.7.0 (2013/07/27) Exception を throw するとき、一旦、errMsg 変数にセットします。 474 String errMsg = "配列型テーブルモデルがセットされていないため、#line( String,int )メソッドはできません。" + CR 475 + " line( " + key + "," + rw + " );" + CR ; 476 throw new RuntimeException( errMsg ); 477 } 478 else if( rw < 0 || rw >= table.getRowCount() ) { 479 return null; 480 } 481 else { 482 int col = table.getColumnNo( key ); 483 if( col < 0 ) { 484 return null; 485 } 486 else { 487 return table.getValue( rw, col ); 488 } 489 } 490 } 491 492 /** 493 * 処理中の行の指定されたキー(カラム名)の値をint型に変換して返します。 494 * 495 * @param key キー 496 * 497 * @return 値 498 */ 499 final protected int linei( final String key ) { 500 return line( key ) == null ? 0 : Integer.valueOf( line( key ) ); 501 } 502 503 /** 504 * メインの配列型テーブルモデルに対して、行を指定して値をint型に変換して返します。 505 * 指定された行が範囲を超えている場合は、nullを返します。 506 * 507 * @param key キー 508 * @param rw 行番号(インデックス) 509 * 510 * @return 値 511 */ 512 final protected int linei( final String key, final int rw ) { 513 return line( key, rw ) == null ? 0 : Integer.valueOf( line( key, rw ) ); 514 } 515 516 /** 517 * 処理中の行の指定されたキー(カラム名)の値をdouble型に変換して返します。 518 * 519 * @param key キー 520 * 521 * @return 値 522 */ 523 final protected double lined( final String key ) { 524 return line( key ) == null ? 0.0 : Double.valueOf( line( key ) ); 525 } 526 527 /** 528 * メインの配列型テーブルモデルに対して、行を指定して値をdouble型に変換して返します。 529 * 指定された行が範囲を超えている場合は、nullを返します。 530 * 531 * @param key キー 532 * @param rw 行番号(インデックス) 533 * 534 * @return 値 535 */ 536 final protected double lined( final String key, final int rw ) { 537 return line( key, rw ) == null ? 0.0 : Double.valueOf( line( key, rw ) ); 538 } 539 540 /** 541 * テーブルのカラム名の一覧を配列形式で返します。 542 * 543 * @og.rev 5.6.7.0 (2013/07/27) Exception を throw するとき、一旦、errMsg 変数にセットします。 544 * 545 * @return テーブルのカラム名配列 546 */ 547 final protected String[] lineKeys() { 548 if( table == null ) { 549 // 5.6.7.0 (2013/07/27) Exception を throw するとき、一旦、errMsg 変数にセットします。 550 String errMsg = "配列型テーブルモデルがセットされていないため、#lineKeys()メソッドはできません。" ; 551 throw new RuntimeException( errMsg ); 552 } 553 else { 554 return table.getNames(); 555 } 556 } 557 558 /** 559 * テーブルにカラムが存在しているかを返します。 560 * 561 * @og.rev 5.2.0.0 (2010/09/01) 562 * @og.rev 5.6.7.0 (2013/07/27) Exception を throw するとき、一旦、errMsg 変数にセットします。 563 * 564 * @param clm カラム名 565 * 566 * @return 存在している場合true、存在していない場合false 567 */ 568 final protected boolean isLine( final String clm ) { 569 if( table == null ) { 570 // 5.6.7.0 (2013/07/27) Exception を throw するとき、一旦、errMsg 変数にセットします。 571 String errMsg = "配列型テーブルモデルがセットされていないため、#isLine( String )メソッドはできません。" + CR 572 + " isLine( " + clm + " );" + CR ; 573 throw new RuntimeException( errMsg ); 574 } 575 return table.getColumnNo( clm ) >= 0 ; 576 } 577 578 /** 579 * 業務ロジックの戻り値をセットします。 580 * 581 * @param rtn 戻り値 582 */ 583 final protected void rtn( final String rtn ) { 584 bizRtn = rtn; 585 } 586 587 /** 588 * 子ロジックを実行します。 589 * 実行する子ロジックの呼び出しは、親クラスと同じソースパス、クラスパスで呼び出しされます。 590 * 子ロジックに渡す引数には、{@XXXX}形式及び[XXXX]形式の変数を使用することができます。 591 * また、子ロジックの戻り値は、val("SUB_RETURN")で取得することができます。 592 * 593 * @param subLogicName 子ロジック名 594 * @param key キー(CSV形式) 595 * @param val 値(CSV形式) 596 * 597 * @return 処理が正常終了したか 598 */ 599 final protected boolean call( String subLogicName, String key, String val ) { 600 return call( subLogicName, key, val, row, table ); 601 } 602 603 /** 604 * 子ロジックを実行します。 605 * 実行する子ロジックの呼び出しは、親クラスと同じソースパス、クラスパスで呼び出しされます。 606 * 子ロジックに渡す引数には、{@XXXX}形式及び[XXXX]形式の変数を使用することができます。 607 * この場合の値は、引数で指定された、配列型テーブルモデルの行に対応する値になります。 608 * また、子ロジックの戻り値は、val("RETURN")で取得することができます。 609 * 610 * @og.rev 5.1.9.0 (2010/08/01) シーケンス対応 611 * @og.rev 5.4.1.0 (2011/11/01) 値にカンマが含まれている場合に正しく動作しないバグを修正 612 * @og.rev 5.6.7.0 (2013/07/27) Exception を throw するとき、一旦、errMsg 変数にセットします。 613 * 614 * @param subLogicName 子ロジック名 615 * @param key キー(CSV形式) 616 * @param val 値(CSV形式) 617 * @param rw 行番号(インデックス) 618 * @param tbl 配列型テーブルモデル 619 * 620 * @return 処理が正常終了したか 621 */ 622 final protected boolean call( String subLogicName, String key, String val, int rw, ArrayTableModel tbl ) { 623 AbstractBizLogic subLogic = (AbstractBizLogic)loader.newInstance( subLogicName ); 624 625 if( subLogic.isRequireTable() ) { 626 // 5.6.7.0 (2013/07/27) Exception を throw するとき、一旦、errMsg 変数にセットします。 627 String errMsg = "このクラスは、外部からテーブルモデルをセットする必要があるため、子ロジックとして呼び出すことはできません。" + CR 628 + " [クラス名=" + subLogic.getClass().getName() + "]" + CR 629 + " subLogicName =" + subLogicName 630 + " key =[" + key + "]" 631 + " val =[" + val + "]" + CR ; 632 throw new RuntimeException( errMsg ); 633 } 634 635 subLogic.setTransaction( tran ); 636 subLogic.setLoader( loader ); 637 subLogic.setKeys( StringUtil.csv2Array( key ) ); 638 // 5.4.1.0 (2011/11/01) 値にカンマが含まれている場合に正しく動作しないバグを修正 639 String[] vals = StringUtil.csv2Array( val ); 640 for( int i=0; i<vals.length; i++ ) { 641 vals[i] = replaceParam( vals[i], rw, tbl ); 642 } 643 subLogic.setVals( vals ); 644 subLogic.setUserId( variableMap.get( "CON.USERID" ) ); 645 subLogic.setParentPgId( variableMap.get( "CON.PGID" ) ); 646 if( debugFlag ) { 647 subLogic.setDebug(); 648 } 649 650 boolean rtn = false; 651 try { 652 rtn = subLogic.exec(); 653 } 654 catch( Throwable th ) { 655 // 5.6.7.0 (2013/07/27) Exception を throw するとき、一旦、errMsg 変数にセットします。 656 String errMsg = "子ロジックの呼び出しでエラーが発生しました。" + CR 657 + " subLogicName =" + subLogicName + CR 658 + " key =[" + key + "]" 659 + " val =[" + val + "]" + CR ; 660 throw new RuntimeException( errMsg ,th ); 661 } 662 variableMap.put( "RETURN", subLogic.getReturn() ); 663 664 if( debugFlag ) { debug( subLogic.getDebugMsg() ); } 665 666 ErrMsg[] errs = subLogic.getErrMsg().toArray(); 667 if( errs.length > 0 ) { 668 ErrorMessage errMsgTmp = new ErrorMessage(); 669 for( int i = 0; i < errs.length; i++ ) { 670 errMsgTmp.addMessage( errs[i].copy( rw ) ); 671 } 672 errMsg.append( errMsgTmp ); 673 } 674 675 return rtn; 676 } 677 678 /** 679 * SQLを実行します。 680 * SQL文には、{@XXXX}形式及び[XXXX]形式の変数を使用することができます。 681 * select文を発行した場合、その結果セットは、var(カラム名)で取得することができます。 682 * 2行以上が返された場合でも、1行目のみが登録されます。 683 * また、検索件数、更新件数については、var("SQL_ROWCOUNT")で取得することができます。 684 * 685 * @param sq SQL文字列 686 */ 687 final protected void sql( final String sq ) { 688 sql( sq, row, table ); 689 } 690 691 /** 692 * SQLを実行します。 693 * SQL文には、{@XXXX}形式及び[XXXX]形式の変数を使用することができます。 694 * [XXXX]形式の変数の置き換えには、引数で指定された配列型テーブルモデルの行が使用されます。 695 * select文を発行した場合、その結果セットは、var(カラム名)で取得することができます。 696 * 2行以上が返された場合でも、1行目のみが登録されます。 697 * また、検索件数、更新件数については、var("SQL_ROWCOUNT")で取得することができます。 698 * 699 * @param sq SQL文字列 700 * @param rw 行番号(インデックス) 701 * @param tbl 配列型テーブルモデル 702 */ 703 final protected void sql( final String sq, final int rw, final ArrayTableModel tbl ) { 704 ArrayTableModel tbl2 = execSQL( sq, rw, tbl ); 705 706 if( tbl2 != null && tbl2.getRowCount() > 0 ) { 707 String[] names = tbl2.getNames(); 708 String[] vals = tbl2.getValues( 0 ); 709 for( int i = 0; i < names.length; i++ ) { 710 variableMap.put( names[i], vals[i] ); 711 } 712 } 713 } 714 715 /** 716 * シーケンス名よりシーケンスオブジェクトを検索し、次の値を取り出します。 717 * DBに対するシーケンスオブジェクトは予め作成されている必要があります。 718 * 719 * また、MySQLの場合は、シーケンスオブジェクトが実装されていないため、 720 * 内部的には、引数のシーケンス名と同じ名前のテーブルから、Integer型の 721 * "SEQID"という項目名を検索することにより、シーケンスをエミュレートしています。 722 * 723 * @og.rev 5.1.9.0 (2010/08/01) 新規追加 724 * 725 * @param seqName シーケンス名 726 * 727 * @return シーケンス番号 728 * @see org.opengion.fukurou.db.DBFunctionName#getSequence(String,Transaction) 729 */ 730 final protected int seq( final String seqName ) { 731 return dbName.getSequence( seqName, tran ); 732 } 733 734 /** 735 * SQLを実行します。 736 * 737 * @param sq SQL文字列 738 * @param rw 行番号(インデックス) 739 * @param tbl 配列型テーブルモデル 740 * 741 * @og.rev 5.6.7.0 (2013/07/27) Exception を throw するとき、一旦、errMsg 変数にセットします。 742 * 743 * @return 結果セット(配列型テーブルモデル) 744 * 745 * @og.rev 5.1.2.0 (2010/01/01) setObject に ParameterMetaData の getParameterType を渡す。(PostgreSQL対応) 746 * @og.rev 5.1.8.0 (2010/07/01) column名は大文字化し、項目名の取得は#getColumnLabel()で行う。(PotgreSQL対応&バグ修正) 747 * @og.rev 5.3.8.0 (2011/08/01) useParamMetaData を ConnectionFactory経由で取得。(PostgreSQL対応)、setNull 対応 748 */ 749 private ArrayTableModel execSQL( final String sq, final int rw, final ArrayTableModel tbl ) { 750 String sql = sq; 751 752 sql = replaceParam( sql, false ); // [XXXX]の変換はここでは行わない。 753 754 Formatter format = null; 755 if( tbl != null && sql.indexOf( '[' ) >= 0 ) { 756 format = getFormatter( sql, tbl ); 757 sql = format.getQueryFormatString(); 758 } 759 760 PreparedStatement pstmt = null; 761 ResultSet result = null; 762 ArrayTableModel tbl2 = null; 763 try { 764 pstmt = conn.prepareStatement( sql ); 765 if( tbl != null && format != null ) { 766 int[] clmNo = format.getClmNos(); 767 768 // 5.1.2.0 (2010/01/01) setObject に ParameterMetaData の getParameterType を渡す。(PostgreSQL対応) 769 if( useParamMetaData ) { 770 ParameterMetaData pMeta = pstmt.getParameterMetaData(); 771 for( int i = 0; i < clmNo.length; i++ ) { 772 int type = pMeta.getParameterType( i+1 ); 773 // 5.3.8.0 (2011/08/01) setNull 対応 774 String val = tbl.getValue( rw, clmNo[i] ); 775 if( val == null || val.isEmpty() ) { 776 pstmt.setNull( i+1, type ); 777 } 778 else { 779 pstmt.setObject( i+1, val, type ); 780 } 781 } 782 } 783 else { 784 for( int i = 0; i < clmNo.length; i++ ) { 785 pstmt.setObject( i+1, tbl.getValue( rw, clmNo[i] ) ); 786 } 787 } 788 } 789 boolean status = pstmt.execute(); 790 result = pstmt.getResultSet(); 791 792 if( status ) { 793 ResultSetMetaData metaData = result.getMetaData(); 794 int cols = metaData.getColumnCount(); 795 796 String[] names = new String[cols]; 797 for( int i = 0; i < cols; i++ ) { 798 // 5.1.8.0 (2010/07/01) column名は大文字化し、項目名の取得は#getColumnLabel()で行う。(PotgreSQL対応&バグ修正) 799 names[i] = metaData.getColumnLabel( i+1 ).toUpperCase( Locale.JAPAN ); 800 } 801 802 String[][] tblVals = DBUtil.resultToArray( result, false ); 803 tbl2 = new ArrayTableModel( names, tblVals ); 804 805 variableMap.put( "SQL_ROWCOUNT", String.valueOf( pstmt.getFetchSize() ) ); 806 } 807 else { 808 variableMap.put( "SQL_ROWCOUNT", String.valueOf( pstmt.getUpdateCount() ) ); 809 } 810 } 811 catch( SQLException ex ) { 812 // 5.6.7.0 (2013/07/27) Exception を throw するとき、一旦、errMsg 変数にセットします。 813 String errMsg = "配列型テーブルモデルの生成に失敗しました。" + CR 814 + " sql =" + sql + CR 815 + " ArrayTableModel=" + tbl ; 816 throw new RuntimeException( errMsg,ex ); 817 } 818 finally { 819 Closer.resultClose( result ); 820 Closer.stmtClose( pstmt ); 821 } 822 return tbl2; 823 } 824 825 /** 826 * エラーメッセージを追加します。 827 * エラーメッセージの引数には、{@XXXX}形式及び[XXXX]形式の変数を使用することができます。 828 * 829 * @param kekka エラーレベル 830 * @param id エラーメッセージID 831 * @param args エラーメッセージパラメーター 832 */ 833 final protected void error( final int kekka, final String id, final String... args ) { 834 error( row, kekka, id, args ); 835 } 836 837 /** 838 * 行指定でエラーメッセージを追加します。 839 * エラーメッセージの引数には、{@XXXX}形式及び[XXXX]形式の変数を使用することができます。 840 * 841 * @param rw 行番号(インデックス) 842 * @param kekka エラーレベル 843 * @param id エラーメッセージID 844 * @param args エラーメッセージパラメーター 845 */ 846 final protected void error( final int rw, final int kekka, final String id, final String... args ) { 847 errMsg.addMessage( rw, kekka, id, replaceParam( args ) ); 848 } 849 850 /** 851 * パラメーターの必須チェックを行います。 852 * キーは、カンマ区切りで複数指定することができます。 853 * 854 * @param cs カラム(カンマ区切り) 855 * 856 * @return エラーが発生した場合はfalse、それ以外はtrue 857 */ 858 final protected boolean must( final String cs ) { 859 if( cs == null || cs.length() == 0 ) { 860 return true; 861 } 862 863 boolean rtn = true; 864 String[] clms = StringUtil.csv2Array( cs ); 865 for( int i=0; i<clms.length; i++ ) { 866 String val = variableMap.get( clms[i] ); 867 if( val == null || val.length() == 0 ) { 868 error( 2, "ERR0012", "{#" + clms[i] + "}" ); 869 rtn = false; 870 } 871 } 872 return rtn; 873 } 874 875 /** 876 * マスタチェックを行います。 877 * 878 * @og.rev 5.6.3.1 (2013/04/05) isErrThrow 引数を追加 879 * 880 * @see #exist(String, String, String, String, String, String) 881 * @param type エラーチェックのタイプ 882 * @param tblId テーブル名 883 * @param ns カラム(カンマ区切り) 884 * @param vs 値(カンマ区切り) 885 * 886 * @return エラーが発生した場合はfalse、それ以外はtrue 887 */ 888 final protected boolean exist( final String type, final String tblId, final String ns, final String vs ) { 889 return exist( type, tblId, ns, vs, null, null,true ); 890 } 891 892 /** 893 * マスタチェックを行います。 894 * 895 * 引数に指定されたテーブル名、及び条件句を生成するためのカラム、値から 896 * 件数を取得し、typeに応じて件数チェックを行います。 897 * (カラム、値には、カンマ区切りで複数指定することができます) 898 * type=true 存在する場合true 存在しない場合false 899 * type=false 存在する場合false 存在しない場合true 900 * type=one 1件以内 true 2件以上 false 901 * 902 * 必須チェックの引数には、{@XXXX}形式及び[XXXX]形式の変数を使用することができます。 903 * 904 * また、固定値カラム、値にも条件となるカラム及び値を指定することができますが、 905 * ここで指定されたカラムは、エラーメッセージ表示時にカラム、値が画面に表示されません。 906 * 907 * @og.rev 5.6.3.1 (2013/04/05) isErrThrow 引数を追加 908 * 909 * @param type エラーチェックのタイプ 910 * @param tblId テーブル名 911 * @param ns カラム(カンマ区切り) 912 * @param vs 値(カンマ区切り) 913 * @param conNs 固定値カラム(カンマ区切り) 914 * @param conVs 固定値(カンマ区切り) 915 * 916 * @return エラーが発生した場合はfalse、それ以外はtrue 917 */ 918 final protected boolean exist( final String type, final String tblId 919 , final String ns, final String vs, final String conNs, final String conVs ) { 920 return exist( type, tblId, ns, vs, conNs, conVs,true ); 921 } 922 923 /** 924 * マスタチェックを行います。 925 * 引数に指定されたテーブル名、及び条件句を生成するためのカラム、値から 926 * 件数を取得し、typeに応じて件数チェックを行います。 927 * (カラム、値には、カンマ区切りで複数指定することができます) 928 * type=true 存在する場合true 存在しない場合false 929 * type=false 存在する場合false 存在しない場合true 930 * type=one 1件以内 true 2件以上 false 931 * 932 * 必須チェックの引数には、{@XXXX}形式及び[XXXX]形式の変数を使用することができます。 933 * 934 * また、固定値カラム、値にも条件となるカラム及び値を指定することができますが、 935 * ここで指定されたカラムは、エラーメッセージ表示時にカラム、値が画面に表示されません。 936 * 937 * isErrThrow は、エラーが発生した場合に、エラーメッセージ(ErrorMessage)に書き込むかどうかを指定します。 938 * 基本は、互換性を考慮し、true(書き込む)です。 939 * false にするケースは、存在チェックを行い、あれば更新、なければ追加 など後続処理を行いたい場合に使います。 940 * 941 * @og.rev 5.6.3.1 (2013/04/05) isErrThrow 引数を追加 942 * @og.rev 5.6.7.0 (2013/07/27) Exception を throw するとき、一旦、errMsg 変数にセットします。 943 * 944 * @param type エラーチェックのタイプ 945 * @param tblId テーブル名 946 * @param ns カラム(カンマ区切り) 947 * @param vs 値(カンマ区切り) 948 * @param conNs 固定値カラム(カンマ区切り) 949 * @param conVs 固定値(カンマ区切り) 950 * @param isErrThrow 判定結果がfalseの場合に、error関数を呼ぶ場合は、true。呼ばない場合は、falseをセットします。 951 * 952 * @return エラーが発生した場合はfalse、それ以外はtrue 953 */ 954 final protected boolean exist( final String type, final String tblId 955 , final String ns, final String vs, final String conNs, final String conVs, final boolean isErrThrow ) { 956 if( ns == null || ns.length() == 0 || vs == null || vs.length() == 0 ) { 957 // 5.6.7.0 (2013/07/27) Exception を throw するとき、一旦、errMsg 変数にセットします。 958 String errMsg = "カラム又は、値にnullは指定できません。" + CR 959 + " ns =[" + ns + "]" 960 + " vs =[" + vs + "]" ; 961 throw new RuntimeException( errMsg ); 962 } 963 964 String namesStr = ns + ( conNs == null || conNs.length() == 0 ? "" : "," + conNs ); 965 String[] namesArr = StringUtil.csv2Array( namesStr ); 966 String valsStr = vs + ( conVs == null || conVs.length() == 0 ? "" : "," + conVs ); 967 String[] valsArr = StringUtil.csv2Array( valsStr ); 968 if( namesArr.length != valsArr.length ) { 969 // 5.6.7.0 (2013/07/27) Exception を throw するとき、一旦、errMsg 変数にセットします。 970 String errMsg = "カラムと値の個数が異なります。" + CR 971 + " names = [" + namesStr + "]" + CR 972 + " vals = [" + valsStr + "]"; 973 throw new RuntimeException( errMsg ); 974 } 975 976 StringBuilder sb = new StringBuilder(); 977 sb.append( "select count(*) CNT from " ).append( tblId ); 978 for( int i=0 ;i<namesArr.length; i++ ) { 979 if( i==0 ) { sb.append( " where " ); } 980 else { sb.append( " and " ); } 981 sb.append( namesArr[i] ).append( " = " ).append( valsArr[i] ); 982 } 983 984 int count = 0; 985 ArrayTableModel tbl2 = execSQL( sb.toString(), row, table ); 986 if( tbl2 != null && tbl2.getRowCount() >= 0 ) { 987 count = Integer.valueOf( tbl2.getValues( 0 )[0] ); 988 } 989 990 String repVals = replaceParam( vs ); 991 if( "true".equalsIgnoreCase( type ) ) { 992 // ERR0025=データ未登録エラー。キー={0}、値={1} のデータは、存在していません。 993 if( count <= 0 ) { 994 if( isErrThrow ) { error( NG, "ERR0025", "{#" + ns + "}", repVals ); } // 5.6.3.1 (2013/04/05) 995 return false; 996 } 997 } 998 else if( "false".equalsIgnoreCase( type ) ) { 999 // ERR0026=データ登録済みエラー。キー={0}、値={1} のデータは、すでに存在しています。 1000 if( count > 0 ) { 1001 if( isErrThrow ) { error( NG, "ERR0026", "{#" + ns + "}", repVals ); } // 5.6.3.1 (2013/04/05) 1002 return false; 1003 } 1004 } 1005 else if( "one".equalsIgnoreCase( type ) ) { 1006 // ERR0027=データ2重登録エラー。キー={0}、値={1} のデータは、重複して存在しています。 1007 if( count > 1 ) { 1008 if( isErrThrow ) { error( NG, "ERR0027", "{#" + ns + "}", repVals ); } // 5.6.3.1 (2013/04/05) 1009 return false; 1010 } 1011 } 1012 else { 1013 // 5.6.7.0 (2013/07/27) Exception を throw するとき、一旦、errMsg 変数にセットします。 1014 String errMsg = "typeは、true、false、oneのいずれかで指定する必要があります。" + CR 1015 + " type = [" + type + "]"; 1016 throw new RuntimeException( errMsg ); 1017 } 1018 return true; 1019 } 1020 1021 /** 1022 * 引数に指定されたキー、値をマップ形式に変換します。 1023 * 1024 * @og.rev 5.5.7.2 (2012/10/09) HybsDateUtil を利用するように修正します。 1025 * @og.rev 5.6.7.0 (2013/07/27) Exception を throw するとき、一旦、errMsg 変数にセットします。 1026 */ 1027 private void makeParamMap() { 1028 if( keys != null && vals != null ) { 1029 if( keys.length == vals.length ) { 1030 for( int i = 0; i < keys.length; i++ ) { 1031 paramKeysStr.append( keys[i] ).append( "|" ); 1032 variableMap.put( keys[i], vals[i] ); 1033 } 1034 } 1035 else { 1036 // 5.6.7.0 (2013/07/27) Exception を throw するとき、一旦、errMsg 変数にセットします。 1037 String errMsg = "keysとvalsの個数が異なります。" + CR 1038 + " keys =" + Arrays.toString( keys ) + CR 1039 + " vals =" + Arrays.toString( vals ) ; 1040 throw new RuntimeException( errMsg ); 1041 } 1042 } 1043 1044 String ymdh = HybsDateUtil.getDate( "yyyyMMddHHmmss" ); // 5.5.7.2 (2012/10/09) HybsDateUtil を利用 1045 variableMap.put( "CON.YMDH", ymdh ); 1046 variableMap.put( "CON.YMD", ymdh.substring( 0,8 ) ); 1047 variableMap.put( "CON.HMS", ymdh.substring( 8 ) ); 1048 1049 variableMap.put( "CON.PGID", this.getClass().getSimpleName() ); 1050 } 1051 1052 /** 1053 * {@XXXX}形式及び[XXXX]形式の文字列の置き換えを行います。 1054 * 1055 * @param str 置き換え対象の文字列 1056 * 1057 * @return 置き換え結果の文字列 1058 */ 1059 private String replaceParam( final String str ) { 1060 return replaceParam( str, row, table ); 1061 } 1062 1063 /** 1064 * {@XXXX}形式及び[XXXX]形式の文字列の置き換えを行います。 1065 * isRepTableにfalseを指定した場合、Formatterによる[XXXX]変換は行われません。 1066 * (SQLの変換の場合は、PreparedStatementで処理させるため、[XXXX]の変換は行わない。) 1067 * 1068 * @param str 置き換え対象の文字列 1069 * @param isRepTable Formatterによる[XXXX]変換を行うか 1070 * 1071 * @return 置き換え結果の文字列 1072 */ 1073 private String replaceParam( final String str, final boolean isRepTable ) { 1074 return isRepTable ? replaceParam( str, row, table) : replaceParam( str, 0, null ) ; 1075 } 1076 1077 /** 1078 * {@XXXX}形式及び[XXXX]形式の文字列の置き換えを行います。 1079 * [XXXX]形式の置き換えには、引数で指定された配列型テーブルモデル、行番号(インデックス)を使用します。 1080 * 1081 * @og.rev 5.1.8.0 (2010/07/01) 引数チェック漏れ対応 1082 * @og.rev 5.3.9.0 (2011/09/01) nullが連続する場合にゼロストリングに置き換えられないバグを修正 1083 * 1084 * @param str 置き換え対象の文字列 1085 * @param rw 行番号(インデックス) 1086 * @param tbl 配列型テーブルモデル 1087 * 1088 * @return 置き換え結果の文字列 1089 */ 1090 private String replaceParam( final String str, final int rw, final ArrayTableModel tbl ) { 1091 // 5.1.8.0 (2010/07/01) 引数チェック漏れ対応 1092 if( str == null || str.length() == 0 ) { return ""; } 1093 1094 String rtn = str; 1095 1096 // {@XXXX}の変換 1097 if( variableMap.size() > 0 && rtn.indexOf( "{@" ) >= 0 ) { 1098 SystemParameter sysParam = getSysParam( rtn ); 1099 rtn = sysParam.replace( variableMap ); 1100 } 1101 1102 // [XXXX]の変換 1103 if( tbl != null && rtn.indexOf( '[' ) >= 0 ) { 1104 Formatter format = getFormatter( rtn, tbl ); 1105 rtn = format.getFormatString( rw ); 1106 // 以下3行はFormatterのバグを吸収(値がnullの場合に"null"という文字列で出力されてしまう) 1107 // 5.3.9.0 (2011/09/01) nullが連続する場合にゼロストリングに置き換えられないバグを修正 1108 rtn = ',' + rtn; 1109 rtn = rtn.replace( ",null", "," ); 1110 rtn = rtn.substring( 1 ); 1111 } 1112 1113 return rtn; 1114 } 1115 1116 /** 1117 * {@XXXX}形式及び[XXXX]形式の文字列(配列)の置き換えを行います。 1118 * 1119 * @param str 置き換え対象の文字列(配列) 1120 * 1121 * @return 置き換え結果の文字列 1122 */ 1123 private String[] replaceParam( final String[] str ) { 1124 return replaceParam( str, row, table ); 1125 } 1126 1127 /** 1128 * {@XXXX}形式及び[XXXX]形式の文字列(配列)の置き換えを行います。 1129 * [XXXX]形式の置き換えには、引数で指定された配列型テーブルモデル、行番号(インデックス)を使用します。 1130 * 1131 * @param str 置き換え対象の文字列(配列) 1132 * @param rw 行番号(インデックス) 1133 * @param tbl 配列型テーブルモデル 1134 * 1135 * @return 置き換え結果の文字列 1136 */ 1137 private String[] replaceParam( final String[] str, final int rw, final ArrayTableModel tbl ) { 1138 for( int i = 0; i < str.length; i++ ) { 1139 str[i] = replaceParam( str[i], rw, tbl ); 1140 } 1141 return str; 1142 } 1143 1144 /** 1145 * [XXXX]変換を行うためのFormatterを取得します。 1146 * 1147 * @param str 変換文字列 1148 * @param tbl 配列型テーブルモデル 1149 * 1150 * @return Formatterオブジェクト 1151 */ 1152 private Formatter getFormatter( final String str, final ArrayTableModel tbl ) { 1153 Formatter format = formatMap.get( str + tbl.toString() ); 1154 if( format == null ) { 1155 format = new Formatter( tbl ); 1156 format.setFormat( str ); 1157 formatMap.put( str + tbl.toString(), format ); 1158 } 1159 return format; 1160 } 1161 1162 /** 1163 * {@XXXX}変換を行うためのSystemParameterオブジェクトを取得します。 1164 * 1165 * @param str 変換文字列 1166 * 1167 * @return SystemParameterオブジェクト 1168 */ 1169 private SystemParameter getSysParam( final String str ) { 1170 SystemParameter sysParam = sysParamMap.get( str ); 1171 if( sysParam == null ) { 1172 sysParam = new SystemParameter( str ); 1173 sysParamMap.put( str, sysParam ); 1174 } 1175 return sysParam; 1176 } 1177 1178 /** 1179 * 検索SQLを実行し、結果を配列型テーブルモデルとして返します。 1180 * SQL文には、{@XXXX}形式及び[XXXX]形式の変数を使用することができます。 1181 * また、検索件数については、var("SQL_ROWCOUNT")で取得することができます。 1182 * 1183 * @param sq SQL文 1184 * 1185 * @return 配列型テーブルモデル 1186 */ 1187 final protected ArrayTableModel createTableBySql( final String sq ) { 1188 return createTableBySql( sq, row, table ); 1189 } 1190 1191 /** 1192 * 検索SQLを実行し、結果を配列型テーブルモデルとして返します。 1193 * SQL文には、{@XXXX}形式及び[XXXX]形式の変数を使用することができます。 1194 * [XXXX]形式の変数の置き換えには、引数で指定された配列型テーブルモデルの行が使用されます。 1195 * また、検索件数については、var("SQL_ROWCOUNT")で取得することができます。 1196 * 1197 * @param sq SQL文 1198 * @param rw 行番号(インデックス) 1199 * @param tbl 配列型テーブルモデル 1200 * 1201 * @return 配列型テーブルモデル 1202 */ 1203 final protected ArrayTableModel createTableBySql( final String sq, final int rw, final ArrayTableModel tbl ) { 1204 return execSQL( sq, rw, tbl ); 1205 } 1206}