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.hayabusa.db; 017 018import java.sql.Connection; 019import java.sql.ResultSet; 020import java.sql.SQLException; 021 022import org.opengion.fukurou.system.HybsConst ; // 6.1.0.0 (2014/12/26) 023import org.opengion.fukurou.system.ThrowUtil; // 6.4.2.0 (2016/01/29) 024import org.opengion.fukurou.util.ErrorMessage; 025import org.opengion.hayabusa.common.HybsSystem; 026import org.opengion.hayabusa.common.HybsSystemException; 027import org.opengion.hayabusa.resource.ResourceManager; 028 029/** 030 * Query インターフェースを継承した Query の実装クラスです。 031 * クエリークラスにステートメントを与えて execute()することにより内部に DBTableModel を 032 * 作成します。 033 * このクラスは、Abstract クラスのため、実装は個々のサブクラスで行います。 034 * 唯一実装する必要があるのは、execute() メソッドだけです。 035 * 036 * @og.group DB検索 037 * @og.group DB登録 038 * 039 * @version 4.0 040 * @author Kazuhiko Hasegawa 041 * @since JDK5.0, 042 */ 043public class AbstractQuery implements Query { 044 /** システムの改行コードを設定します。*/ 045 protected static final String CR = HybsConst.CR; // 6.1.0.0 (2014/12/26) refactoring 046 /** StringBilderなどの初期値を設定します。 {@value} */ 047 protected static final int BUFFER_MIDDLE = HybsConst.BUFFER_MIDDLE; // 6.1.0.0 (2014/12/26) refactoring 048 049 private Connection connection ; 050 private int rtnCode = ErrorMessage.OK; 051 private ErrorMessage errMessage ; 052 private ResourceManager resource ; 053 054 private DBTableModel table ; 055 private String stmtString ; 056 private int executeCount = -1 ; 057 private int skipRowCount ; 058 private int maxRowCount = HybsSystem.sysInt( "DB_MAX_ROW_COUNT" ) ; 059 private boolean updateFlag = true ; 060 private DBEditConfig config ; // 5.3.6.0 (2011/06/01) 061 062 // 5.1.9.0 (2010/08/01) DB_RETRY_COUNT,DB_RETRY_TIME 廃止 063 /** データ検索時の最大処理制限時間 */ 064 protected static final int DB_MAX_QUERY_TIMEOUT = HybsSystem.sysInt( "DB_MAX_QUERY_TIMEOUT" ) ; 065 066 /** 6.9.3.0 (2018/03/26) データ検索時のフェッチサイズ {@value} */ 067 protected static final int DB_FETCH_SIZE = HybsConst.DB_FETCH_SIZE; // 6.9.4.1 (2018/04/09) 068 069// /** データ検索時のフェッチサイズを設定します。 */ 070// protected static final int DB_FETCH_SIZE = HybsConst.DB_FETCH_SIZE; // 6.9.4.1 (2018/04/09) 071 072 // 3.5.2.0 (2003/10/20) 内部オブジェクトタイプ名を システムパラメータ で定義します。 073 /** 内部オブジェクトタイプ名 {@value} */ 074 public static final String ARG_ARRAY = "ARG_ARRAY" ; 075 /** 内部オブジェクトタイプ名 {@value} */ 076 public static final String SYSARG_ARRAY = "SYSARG_ARRAY" ; 077 /** 内部オブジェクトタイプ名 {@value} */ 078 public static final String ERR_MSG = "ERR_MSG" ; 079 /** 内部オブジェクトタイプ名 {@value} */ 080 public static final String ERR_MSG_ARRAY = "ERR_MSG_ARRAY" ; 081 082 private String updQuery ; // 7.2.9.1 (2020/10/23) 083 private String insQuery ; // 7.2.9.1 (2020/10/23) 084 private String selQuery ; // 7.4.1.0 (2021/04/23) 085 086 /** 087 * デフォルトコンストラクター 088 * 089 * @og.rev 6.4.2.0 (2016/01/29) PMD refactoring. Each class should declare at least one constructor. 090 */ 091 protected AbstractQuery() { super(); } // これも、自動的に呼ばれるが、空のメソッドを作成すると警告されるので、明示的にしておきます。 092 093 /** 094 * Connectionオブジェクトを外部から設定します。 095 * 096 * 通常は、Transaction と 接続先(DBID) を使用して作成した Connection を渡します。 097 * このクラスでは、Connection の close() や、ConnectionFactory への返却なども 098 * 行いません。それらは、外部処理(通常は、Transactionオブジェクト)で行います。 099 * 100 * Connection には、null は登録できません。 101 * 102 * @og.rev 6.3.6.1 (2015/08/28) 新規追加 103 * 104 * @param conn Connectionオブジェクト 105 */ 106 @Override // Query 107 public void setConnection( final Connection conn ) { 108 if( conn == null ) { 109 final String errMsg = "Connection に null は指定できません。" + CR ; 110 throw new HybsSystemException( errMsg ); 111 } 112 connection = conn; 113 } 114 115 /** 116 * ステートメント文字列をセットします。 117 * 118 * @og.rev 3.1.1.0 (2003/03/28) 同期メソッド(synchronized付き)を非同期に変更する。 119 * 120 * @param stmt ステートメント文字列 121 * 122 */ 123 @Override // Query 124 public void setStatement( final String stmt ) { 125 this.stmtString = stmt.trim(); 126 } 127 128 /** 129 * ステートメント文字列を取り出します。 130 * 131 * @return ステートメント文字列 132 * 133 */ 134 @Override // Query 135 public String getStatement() { 136 return stmtString; 137 } 138 139 /** 140 * ステートメント文字列(UPDATE,INSERT)をセットします。 141 * 142 * @og.rev 7.2.9.1 (2020/10/23) TableUpdateParamTag のマージ(UPDATE,INSERT)対応 143 * @og.rev 7.4.1.0 (2021/04/23) sqlType="MERGE" 時のみ有効で、where 条件で存在すれば何もしない 144 * 145 * @param update UPDATEステートメント文字列 146 * @param insert INSERTステートメント文字列 147 * @param select SELECTステートメント文字列(あれば何もしない、なければINSERT処理の判定用) 148 */ 149// public void setMergeStatement( final String update , final String insert ) { 150 @Override // Query 151 public void setMergeStatement( final String update , final String insert , final String select ) { 152 updQuery = update; 153 insQuery = insert; 154 selQuery = select; 155 } 156 157 /** 158 * ステートメント文字列(UPDATE,INSERT,SELECT)を取り出します。 159 * 160 * @og.rev 7.2.9.1 (2020/10/23) TableUpdateParamTag のマージ(UPDATE,INSERT)対応 161 * @og.rev 7.2.9.3 (2020/11/06) 早い段階でエラーにしておきます。 162 * @og.rev 7.4.1.0 (2021/04/23) sqlType="MERGE" 時のみ有効で、where 条件で存在すれば何もしない 163 * 164 * @return ステートメント文字列の配列(UPDATE,INSERTの順番) 165 */ 166 @Override // Query 167 public String[] getMergeStatement() { 168 // if( updQuery == null || insQuery == null ) { 169 // final String errMsg = "Merge処理を行うには、INSERTとUPDATEの両方のQUERYが必要です。" + CR 170 // + " updQuery=" + updQuery + CR 171 // + " insQuery=" + insQuery + CR 172 // + " query =" + stmtString ; 173 // 174 // throw new UnsupportedOperationException( errMsg ); 175 // } 176 177// return new String[] { updQuery,insQuery } ; 178 return new String[] { updQuery,insQuery,selQuery } ; 179 } 180 181 /** 182 * 引数配列付のクエリーを実行します。 183 * 処理自体は、#execute() と同様に、各サブクラスの実装に依存します。 184 * これは、PreparedQuery で使用する引数を配列でセットするものです。 185 * select * from emp where deptno = ? and job = ? などの PreparedQuery や 186 * { call xxxx( ?,?,? ) } などの CallableStatement の ? 部分の引数を 187 * 順番にセットしていきます。 188 * ※ このクラスでは実装されていません。 189 * 190 * @og.rev 6.1.1.0 (2015/01/17) 引数配列を可変引数にして、execute() を含めて定義します。 191 * 192 * @param args オブジェクトの引数配列(可変長引数) 193 */ 194 @Override // Query 195 public void execute( final String... args ) { // 6.1.1.0 (2015/01/17) refactoring 196 final String errMsg = "このクラスでは実装されていません。execute( String... )"; 197 throw new UnsupportedOperationException( errMsg ); 198 } 199 200 /** 201 * 引数配列付のクエリーを実行します。 202 * 処理自体は、#execute() と同様に、各サブクラスの実装に依存します。 203 * これは、PreparedQuery で使用する引数を配列でセットするものです。 204 * select * from emp where deptno = ? and job = ? などの PreparedQuery の 205 * ? 部分の引数を 206 * 順番にセットしていきます。 207 * ※ このクラスでは実装されていません。 208 * 209 * @og.rev 4.0.0.0 (2005/01/31) 新規追加 210 * 211 * @param keys オブジェクトのキー配列 212 * @param args オブジェクトの引数配列(可変長引数) 213 */ 214 @Override // Query 215 public void execute( final String[] keys, final String... args ) { // 6.1.1.0 (2015/01/17) refactoring 216 final String errMsg = "このクラスでは実装されていません。execute( String[],String... )"; 217 throw new UnsupportedOperationException( errMsg ); 218 } 219 220 /** 221 * 引数配列付のクエリーを実行します。 222 * 処理自体は、#execute() と同様に、各サブクラスの実装に依存します。 223 * これは、PreparedQuery で使用する引数を配列でセットするものです。 224 * select * from emp where deptno = ? and job = ? などの PreparedQuery の 225 * ? 部分の引数を 226 * 順番にセットしていきます。 227 * ※ このクラスでは実装されていません。 228 * 229 * @og.rev 4.0.0.0 (2005/01/31) 引数をすべて受け取って実行するメソッドを標準メソッドとして追加 230 * 231 * @param names カラム名(CSV形式) 232 * @param dbArrayType アレイタイプ名称 233 * @param sysArg DBSysArg配列 234 * @param userArg DBUserArg配列 235 */ 236 @Override // Query 237 public void execute( final String names,final String dbArrayType, 238 final DBSysArg[] sysArg,final DBUserArg[] userArg ) { 239 final String errMsg = "このクラスでは実装されていません。execute( String,String,DBSysArg[],DBUserArg[] )"; 240 throw new UnsupportedOperationException( errMsg ); 241 } 242 243 /** 244 * 引数配列付のクエリーを実行します。 245 * 処理自体は、#execute() と同様に、各サブクラスの実装に依存します。 246 * これは、PreparedQuery で使用する引数を配列でセットするものです。 247 * select * from emp where deptno = ? and job = ? などの PreparedQuery の 248 * [カラム名] 部分の引数を、DBTableModelから順番にセットしていきます。 249 * ※ このクラスでは実装されていません。 250 * 251 * @param rowNo 選択された行番号配列(登録する対象行) 252 * @param table DBTableModelオブジェクト(登録する元データ) 253 */ 254 @Override // Query 255 public void execute( final int[] rowNo, final DBTableModel table ) { 256 final String errMsg = "このクラスでは実装されていません。execute( final int[] rowNo, final DBTableModel table )"; 257 throw new UnsupportedOperationException( errMsg ); 258 } 259 260 /** 261 * クエリーの実行結果件数をセットします。 262 * 初期値は -1 です。(クエリーが失敗した場合や、CallableStatement の呼び出し等で 263 * 実行件数が明確でない場合の戻り値)。 264 * 265 * @og.rev 3.1.1.0 (2003/03/28) 同期メソッド(synchronized付き)を非同期に変更する。 266 * 267 * @param executeCount 実行結果件数 268 */ 269 protected void setExecuteCount( final int executeCount ) { 270 this.executeCount = executeCount; 271 } 272 273 /** 274 * クエリーの実行結果を返します。 275 * クエリーが失敗した場合や、CallableStatement の呼び出し等で実行件数が明確でない 276 * 場合は、-1 が返されます。 277 * 278 * @return 実行結果件数 279 */ 280 @Override // Query 281 public int getExecuteCount() { 282 return executeCount; 283 } 284 285 /** 286 * DBTableModel をセットします。 287 * なお、検索系実行前に setDBTableModel() でテーブルをセットしていたとしても 288 * そのオブジェクトは破棄されて、新しい DBTableModel が生成されます。 289 * 290 * @og.rev 3.1.1.0 (2003/03/28) 同期メソッド(synchronized付き)を非同期に変更する。 291 * 292 * @param table DBTableModelオブジェクト 293 */ 294 protected void setDBTableModel( final DBTableModel table ) { 295 this.table = table; 296 } 297 298 /** 299 * 実行結果の DBTableModel を返します。 300 * 301 * @return DBTableModelオブジェクト 302 */ 303 @Override // Query 304 public DBTableModel getDBTableModel() { 305 return table; 306 } 307 308 /** 309 * データベースの最大検索件数を返します。 310 * (初期値:DB_MAX_ROW_COUNT[={@og.value SystemData#DB_MAX_ROW_COUNT}])。 311 * データベース自体の検索は、指定されたSQLの全件を検索しますが、 312 * DBTableModelのデータとして登録する最大件数をこの値に設定します。0は無制限です。 313 * サーバーのメモリ資源と応答時間の確保の為です。 314 * 315 * @return 最大検索件数 316 */ 317 @Override // Query 318 public int getMaxRowCount() { 319 return maxRowCount; 320 } 321 322 /** 323 * データベースの最大検索件数をセットします。 324 * データベース自体の検索は、指定されたSQLの全件を検索しますが、 325 * DBTableModelのデータとして登録する最大件数をこの値に設定します。 326 * サーバーのメモリ資源と応答時間の確保の為です。 327 * ゼロ、または、負の値を設定すると、無制限(Integer.MAX_VALUE)になります。 328 * 329 * @og.rev 3.1.1.0 (2003/03/28) 同期メソッド(synchronized付き)を非同期に変更する。 330 * @og.rev 4.0.0.0 (2005/08/31) ゼロ、または、負の値は、無制限(Integer.MAX_VALUE)にする。 331 * 332 * @param maxRowCount 最大検索件数 333 */ 334 @Override // Query 335 public void setMaxRowCount( final int maxRowCount ) { 336 this.maxRowCount = maxRowCount > 0 ? maxRowCount : Integer.MAX_VALUE ; 337 } 338 339 /** 340 * データベースの検索スキップ件数を返します。 341 * データベース自体の検索は、指定されたSQLの全件を検索しますが、 342 * DBTableModelのデータとしては、スキップ件数分は登録されません。 343 * サーバーのメモリ資源と応答時間の確保の為です。 344 * 345 * @return 最大検索件数 346 */ 347 @Override // Query 348 public int getSkipRowCount() { 349 return skipRowCount; 350 } 351 352 /** 353 * データベースの検索スキップ件数をセットします。 354 * データベース自体の検索は、指定されたSQLの全件を検索しますが、 355 * DBTableModelのデータとしては、スキップ件数分は登録されません。 356 * サーバーのメモリ資源と応答時間の確保の為です。 357 * 358 * @og.rev 3.1.1.0 (2003/03/28) 同期メソッド(synchronized付き)を非同期に変更する。 359 * 360 * @param skipRowCount スキップ件数 361 */ 362 @Override // Query 363 public void setSkipRowCount( final int skipRowCount ) { 364 this.skipRowCount = skipRowCount; 365 } 366 367 /** 368 * アップデートフラグをセットします。 369 * これは、Query で更新処理の SQL 文を実行したときにセットされます。 370 * 更新処理が実行:true / 検索処理のみ:false をセットします。 371 * このメソッドを呼び出さない場合は、デフォルト:true です。 372 * 373 * @og.rev 2.1.2.3 (2002/12/02) データベース更新時に、更新フラグをセットするように変更 374 * @og.rev 3.1.1.0 (2003/03/28) 同期メソッド(synchronized付き)を非同期に変更する。 375 * 376 * @param up アップデートされたかどうか[true:更新処理/false:検索処理] 377 */ 378 protected void setUpdateFlag( final boolean up ) { 379 updateFlag = up; 380 } 381 382 /** 383 * アップデートフラグを取得します。 384 * これは、Query で更新処理の SQL 文を実行したときに true にセットされます。 385 * 更新処理が実行:true / 検索処理のみ:false を取得できます。 386 * 387 * @og.rev 2.1.2.3 (2002/12/02) データベース更新時に、更新フラグをセットするように変更 388 * @og.rev 4.0.0.0 (2007/07/20) メソッド名変更( getUpdateFlag() ⇒ isUpdate() ) 389 * 390 * @return アップデートされたかどうか[true:更新処理/false:検索処理] 391 */ 392 @Override // Query 393 public boolean isUpdate() { 394 return updateFlag ; 395 } 396 397 /** 398 * リソースマネージャーをセットします。 399 * これは、言語(ロケール)に応じた DBColumn をあらかじめ設定しておく為に 400 * 必要です。 401 * リソースマネージャーが設定されていない、または、所定のキーの DBColumn が 402 * リソースに存在しない場合は、内部で DBColumn オブジェクトを作成します。 403 * 404 * @og.rev 4.0.0.0 (2005/01/31) lang ⇒ ResourceManager へ変更 405 * 406 * @param resource リソースマネージャー 407 */ 408 @Override // Query 409 public void setResourceManager( final ResourceManager resource ) { 410 this.resource = resource; 411 } 412 413 /** 414 * エラーコード を取得します。 415 * エラーコード は、ErrorMessage クラスで規定されているコードです。 416 * 417 * @return エラーコード 418 */ 419 @Override // Query 420 public int getErrorCode() { 421 return rtnCode; 422 } 423 424 /** 425 * エラーコード をセットします。 426 * エラーコード は、ErrorMessage クラスで規定されているコードです。 427 * 428 * @param cd エラーコード 429 */ 430 protected void setErrorCode( final int cd ) { 431 rtnCode = cd; 432 } 433 434 /** 435 * エラーメッセージオブジェクト を取得します。 436 * 437 * @return エラーメッセージオブジェクト 438 */ 439 @Override // Query 440 public ErrorMessage getErrorMessage() { 441 return errMessage; 442 } 443 444 /** 445 * エラーメッセージオブジェクト をセットします。 446 * 447 * @param em エラーメッセージオブジェクト 448 */ 449 protected void setErrorMessage( final ErrorMessage em ) { 450 errMessage = em; 451 } 452 453 /** 454 * 編集設定オブジェクトをセットします。 455 * 456 * @og.rev 5.3.6.0 (2011/06/01) 新規追加 457 * 458 * @param config 編集設定オブジェクト 459 */ 460 @Override // Query 461 public void setEditConfig( final DBEditConfig config ) { 462 this.config = config; 463 } 464 465 /** 466 * 編集設定オブジェクトを取得します。 467 * 468 * @og.rev 5.3.6.0 (2011/06/01) 新規追加 469 * 470 * @return 編集設定オブジェクト 471 */ 472 protected DBEditConfig getEditConfig() { 473 return config; 474 } 475 476 ////////////////////////////////////////////////////////////////////////// 477 // 478 // 継承時にサブクラスから使用するメソッド類( protected ) 479 // 480 ////////////////////////////////////////////////////////////////////////// 481 482 /** 483 * ResultSet を DBTableModelに割り当てます。 484 * 485 * 毎回、検索毎に DBTableModel にコピーするイメージです。 486 * ResulSet 以外のオブジェクトから、DBTableModelを作成する場合は、 487 * このメソッドをオーバーライドします。 488 * 489 * このメソッドは、execute からのみ呼び出されます。 490 * それ以外からは呼出し出来ません。 491 * 492 * @og.rev 3.1.1.0 (2003/03/28) 同期メソッド(synchronized付き)を非同期に変更する。 493 * @og.rev 3.3.3.3 (2003/08/06) カラムのラベル名を、大文字に変換する。 494 * @og.rev 3.8.5.0 (2006/03/02) CLOB カラムかどうかを判定しCLOBの場合は、Clob オブジェクトから文字列を取り出します。 495 * @og.rev 3.8.8.8 (2007/05/11) ROWID対応(小数点対応 "0.3" が ".3" と表示される対策) 496 * @og.rev 4.0.0.0 (2006/01/31) CLOB カラムかどうかを判定しCLOBの場合は、ストリームから値を取り出します。 497 * @og.rev 5.3.6.0 (2011/06/01) DBTableModel作成処理をDBTableModelUtilに移動&集計機能対応 498 * @og.rev 6.3.6.1 (2015/08/28) close(),realClose() 廃止。Queryはキャッシュしません。 499 * 500 * @param resultSet ResultSetオブジェクト 501 */ 502 protected void createTableModel( final ResultSet resultSet ) { 503 try { 504 if( config == null ) { 505 table = DBTableModelUtil.makeDBTable( resultSet, getSkipRowCount(), maxRowCount, resource ); 506 } 507 else { 508 table = DBTableModelUtil.makeEditDBTable( resultSet, getSkipRowCount(), maxRowCount, resource, config ); 509 } 510 511 setExecuteCount( table.getRowCount() ); 512 } 513 catch( final SQLException ex ) { 514 final String errMsg = "テーブルモデルを作成できませんでした。"; 515 throw new HybsSystemException( errMsg,ex ); // 3.5.5.4 (2004/04/15) 引数の並び順変更 516 } 517 } 518 519 /** 520 * ConnectionFactory.connection( String ); を利用して、Connection 521 * オブジェクトを取り出します。 522 * 523 * コネクションプールが一杯の場合は、即エラーになります。 524 * 525 * @og.rev 3.1.1.0 (2003/03/28) 同期メソッド(synchronized付き)を非同期に変更する。 526 * @og.rev 3.8.7.0 (2006/12/15) アクセスログ取得の為、ApplicationInfoオブジェクトを設定 527 * @og.rev 5.1.9.0 (2010/08/01) transaction 属性追加。 528 * @og.rev 6.3.6.1 (2015/08/28) transaction 属性廃止。内部のConnectionを返します。 529 * 530 * @return コネクション 531 */ 532 protected Connection getConnection() { 533 return connection; 534 } 535 536 /** 537 * この接続が、PreparedStatement#getParameterMetaData() を使用するかどうかを判定します。 538 * 539 * ConnectionFactory#useParameterMetaData(String) の結果を返します。(postgreSQL対応) 540 * 541 * ※ 暫定処理です。もっと、良い方法を考える必要があります。 542 * 543 * @og.rev 5.3.8.0 (2011/08/01) 新規追加 544 * @og.rev 6.3.6.1 (2015/08/28) 内部変数にconnIDが無くなったため、直接所得することになりました。 545 * @og.rev 6.4.2.0 (2016/01/29) ex.printStackTrace() を、ThrowUtil#ogStackTrace(Throwable) に置き換え。 546 * 547 * @return 使用する場合:true / その他:false 548 * @see org.opengion.fukurou.db.ConnectionFactory#useParameterMetaData(String) 549 */ 550 protected boolean useParameterMetaData() { 551 // return ConnectionFactory.useParameterMetaData( connID ); 552 try { 553 return "PostgreSQL".equalsIgnoreCase( connection.getMetaData().getDatabaseProductName() ); 554 } 555 catch( final Throwable th ) { 556 System.err.println( ThrowUtil.ogStackTrace( th ) ); // 6.4.2.0 (2016/01/29) 557 } 558 return false ; 559 } 560 561 ////////////////////////////////////////////////////////////////////////// 562 // 563 // Object クラスのオーバーライド部分 564 // 565 ////////////////////////////////////////////////////////////////////////// 566 567 /** 568 * オブジェクトの識別子として、最後のクエリーを返します。 569 * 570 * @return 最後のクエリー 571 * @og.rtnNotNull 572 */ 573 @Override 574 public String toString() { 575 return "LastQuery :[" + getStatement() + "] "; 576 } 577}