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.db; 017 018import java.sql.CallableStatement; 019import java.sql.Connection; 020import java.sql.PreparedStatement; 021import java.sql.ParameterMetaData; 022import java.sql.ResultSet; 023import java.sql.SQLException; 024import java.sql.Types; 025import java.util.List; // 8.5.4.2 (2024/01/12) PMD 7.0.0 LooseCoupling 026import java.util.ArrayList; 027import java.util.Locale; 028 029import org.opengion.fukurou.system.OgRuntimeException ; // 6.4.2.0 (2016/01/29) 030import org.opengion.fukurou.util.StringUtil; 031import static org.opengion.fukurou.system.HybsConst.CR; // 6.1.0.0 (2014/12/26) refactoring 032import static org.opengion.fukurou.system.HybsConst.DB_FETCH_SIZE; // 6.9.4.1 (2018/04/09) 033 034/** 035 * データベース関連の便利なメソッドを集めた簡易ユーティリティークラスです。 036 * 全てのメソッドは、static メソッドになっています。 037 * 038 * @og.rev 2.1.1.1 (2002/11/15) Serializable インターフェースを削除する。 039 * @og.rev 4.0.0.0 (2007/10/16) DBアクセス関係のメソッドのみをパッケージ移動(hayabusa/db ⇒ fukurou/db) 040 * @og.rev 6.0.4.0 (2014/11/28) ResultSetValue クラスで、ResultSet から値を取得する処理を移植 041 * 042 * @og.group DB/Shell制御 043 * 044 * @version 4.0 045 * @author Kazuhiko Hasegawa 046 * @since JDK5.0, 047 */ 048public final class DBUtil { 049// /** 6.9.3.0 (2018/03/26) データ検索時のフェッチサイズ {@value} */ 050// private static final int DB_FETCH_SIZE = 1001 ; 051 052 /** 053 * デフォルトコンストラクターをprivateにして、 054 * オブジェクトの生成をさせないようにする。 055 */ 056 private DBUtil() {} 057 058 /** 059 * 初期データベースに接続して、Queryを実行します(互換性確保のため残しています)。 060 * 061 * ステートメントと引数により、Prepared クエリーの検索のみ実行します。 062 * 結果は、すべて文字列に変換されて格納されます。 063 * 064 * @og.rev 3.8.7.0 (2006/12/15) アクセスログ取得の為、ApplicationInfoオブジェクトを設定 065 * @og.rev 4.0.0.0 (2007/10/10) dbid の初期値を、"DEFAULT" から null に変更 066 * @og.rev 5.1.9.0 (2010/08/01) Transaction 対応します。 067 * @og.rev 5.3.7.0 (2011/07/01) TransactionReal の引数変更 068 * @og.rev 5.3.8.0 (2011/08/01) TransactionReal と close() 処理をセットで実行する。 069 * @og.rev 6.3.6.1 (2015/08/28) Transaction でAutoCloseableを使用したtry-with-resources構築に対応。 070 * 071 * @param stmt ステートメント文字列 072 * @param args オブジェクトの引数配列 073 * @param appInfo アプリ情報オブジェクト 074 * 075 * @return 検索結果の配列 076 */ 077 public static String[][] dbExecute( final String stmt ,final String[] args ,final ApplicationInfo appInfo ) { 078 try( Transaction tran = new TransactionReal( appInfo ) ) { 079 return dbExecute( stmt, args, tran, null, false ); 080 } 081 } 082 083 /** 084 * 初期データベースに接続して、Queryを実行します(Transaction 対応)。 085 * 086 * ステートメントと引数により、Prepared クエリーの検索のみ実行します。 087 * 結果は、すべて文字列に変換されて格納されます。 088 * ここでは、Transactionオブジェクトから、Connection を取り出して使用します。 089 * 090 * @og.rev 5.1.9.0 (2010/08/01) 新規作成 Transaction 対応 091 * 092 * @param stmt ステートメント文字列 093 * @param args オブジェクトの引数配列 094 * @param tran Transactionオブジェクト 095 * 096 * @return 検索結果の配列 097 */ 098 public static String[][] dbExecute( final String stmt ,final String[] args ,final Transaction tran ) { 099 return dbExecute( stmt, args, tran, null, false ); 100 } 101 102 /** 103 * 検索するデータベースを指定して、Queryを実行します(互換性確保のため残しています)。 104 * 105 * ステートメントと引数により、Prepared クエリーの検索のみ実行します。 106 * 結果は、すべて文字列に変換されて格納されます。 107 * 追加:検索以外のSQLも実行できます。結果は、null を返します。 108 * 109 * @og.rev 3.0.0.0 (2002/12/25) 検索のみのクエリーから、何でもありのクエリーに変更 110 * @og.rev 2.3.1.3 (2003/01/28) Open Cursor が、大量に残る件の対応。ResultSet を close() 111 * @og.rev 3.8.0.8 (2005/10/03) エラーメッセージの出力順をメッセージ+Queryに変更します。 112 * @og.rev 3.8.7.0 (2006/12/15) アクセスログ取得の為、ApplicationInfoオブジェクトを設定 113 * @og.rev 4.0.0.1 (2007/12/03) try ~ catch ~ finally をきちんと行う。 114 * @og.rev 5.1.9.0 (2010/08/01) Transaction 対応します。 115 * @og.rev 5.3.7.0 (2011/07/01) TransactionReal の引数変更 116 * @og.rev 5.3.8.0 (2011/08/01) TransactionReal と close() 処理をセットで実行する。 117 * @og.rev 6.3.6.1 (2015/08/28) Transaction でAutoCloseableを使用したtry-with-resources構築に対応。 118 * 119 * @param stmt ステートメント文字列 120 * @param args オブジェクトの引数配列 121 * @param appInfo アプリ情報オブジェクト 122 * @param dbid 接続先ID 123 * 124 * @return 検索結果の配列 125 */ 126 public static String[][] dbExecute( final String stmt ,final String[] args, final ApplicationInfo appInfo, final String dbid ) { 127 try( Transaction tran = new TransactionReal( appInfo ) ) { 128 return dbExecute( stmt, args, tran, dbid, false ); 129 } 130 } 131 132 /** 133 * 検索するデータベースを指定して、Queryを実行します(Transaction 対応)。 134 * 135 * ステートメントと引数により、Prepared クエリーの検索のみ実行します。 136 * 結果は、すべて文字列に変換されて格納されます。 137 * 追加:検索以外のSQLも実行できます。結果は、null を返します。 138 * ここでは、Transactionオブジェクトから、Connection を取り出して使用します。 139 * 140 * @og.rev 5.1.9.0 (2010/08/01) 新規作成 Transaction 対応 141 * 142 * @param stmt ステートメント文字列 143 * @param args オブジェクトの引数配列 144 * @param tran Transactionオブジェクト 145 * @param dbid 接続先ID 146 * 147 * @return 検索結果の配列 148 */ 149 public static String[][] dbExecute( final String stmt ,final String[] args, final Transaction tran , final String dbid ) { 150 return dbExecute( stmt, args, tran, dbid, false ); 151 } 152 153 /** 154 * 検索するデータベースを指定して、Queryを実行します(互換性確保のため残しています)。 155 * 156 * ステートメントと引数により、Prepared クエリーの検索のみ実行します。 157 * 結果は、すべて文字列に変換されて格納されます。 158 * 追加:検索以外のSQLも実行できます。結果は、null を返します。 159 * 160 * @og.rev 4.3.7.0 (2009/06/01) 新規作成 161 * @og.rev 5.1.2.0 (2010/01/01) setObject に ParameterMetaData の getParameterType を渡す。(PostgreSQL対応) 162 * @og.rev 5.1.9.0 (2010/08/01) Transaction 対応します。 163 * @og.rev 5.3.7.0 (2011/07/01) TransactionReal の引数変更 164 * @og.rev 5.3.8.0 (2011/08/01) TransactionReal と close() 処理をセットで実行する。 165 * @og.rev 6.3.6.1 (2015/08/28) Transaction でAutoCloseableを使用したtry-with-resources構築に対応。 166 * 167 * @param stmt ステートメント文字列 168 * @param args オブジェクトの引数配列 169 * @param appInfo アプリ情報オブジェクト 170 * @param dbid 接続先ID 171 * @param useHeader 1行目にヘッダーを含めるか 172 * 173 * @return 検索結果の配列 174 */ 175 public static String[][] dbExecute( final String stmt ,final String[] args, final ApplicationInfo appInfo, final String dbid, final boolean useHeader ) { 176 try( Transaction tran = new TransactionReal( appInfo ) ) { 177 return dbExecute( stmt, args, tran, dbid, useHeader ); 178 } 179 } 180 181 /** 182 * 検索するデータベースを指定して、Queryを実行します(Transaction 対応)。 183 * 184 * ステートメントと引数により、Prepared クエリーの検索のみ実行します。 185 * 結果は、すべて文字列に変換されて格納されます。 186 * 追加:検索以外のSQLも実行できます。結果は、null を返します。 187 * 188 * @og.rev 5.1.9.0 (2010/08/01) 新規作成 Transaction 対応 189 * @og.rev 5.3.8.0 (2011/08/01) Transaction を引数で受け取った場合は、close() しない。 190 * @og.rev 5.3.8.0 (2011/08/01) useParamMetaData を ConnectionFactory経由で取得。(PostgreSQL対応)、setNull 対応 191 * @og.rev 6.4.2.1 (2016/02/05) try-with-resources 文で記述。 192 * @og.rev 6.4.3.2 (2016/02/19) args が null でなく、length==0 でない場合のみ、処理する。 193 * @og.rev 6.9.3.0 (2018/03/26) データ検索時のフェッチサイズを設定。 194 * @og.rev 8.5.6.1 (2024/03/29) PMD 7.0.0 Finding duplicated code with CPD 195 * 196 * @param stmt ステートメント文字列 197 * @param args オブジェクトの引数配列 198 * @param tran Transactionオブジェクト 199 * @param dbid 接続先ID 200 * @param useHeader 1行目にヘッダーを含めるか 201 * 202 * @return 検索結果の配列 203 */ 204 public static String[][] dbExecute( final String stmt ,final String[] args, final Transaction tran, final String dbid, final boolean useHeader ) { 205 String[][] rtn = null; 206 try { 207 final Connection conn = tran.getConnection( dbid ); // 5.1.9.0 (2010/08/01) Transaction 対応 208 try( PreparedStatement pstmt = conn.prepareStatement( stmt ) ) { 209 pstmt.setFetchSize( DB_FETCH_SIZE ); // 6.9.3.0 (2018/03/26) データ検索時のフェッチサイズ 210 // 8.5.6.1 (2024/03/29) PMD 7.0.0 Finding duplicated code with CPD 211 pstmtValueSet( pstmt, args, dbid ); 212// // 6.4.3.2 (2016/02/19) args が null でなく、length==0 でない場合のみ、処理する。 213// if( args != null && args.length > 0 ) { 214// // 5.1.1.0 (2009/11/11) setObject に ParameterMetaData の getParameterType を渡す。(PostgreSQL対応) 215// final boolean useParamMetaData = ConnectionFactory.useParameterMetaData( dbid ); // 5.3.8.0 (2011/08/01) 216// if( useParamMetaData ) { 217// final ParameterMetaData pMeta = pstmt.getParameterMetaData(); 218// for( int i=0; i<args.length; i++ ) { 219// final int type = pMeta.getParameterType( i+1 ); 220// // 5.3.8.0 (2011/08/01) setNull 対応 221// final String val = args[i]; 222// if( val == null || val.isEmpty() ) { 223// pstmt.setNull( i+1, type ); 224// } 225// else { 226// pstmt.setObject( i+1, val, type ); 227// } 228// } 229// } 230// else { 231// for( int i=0; i<args.length; i++ ) { 232// pstmt.setObject( i+1,args[i] ); 233// } 234// } 235// } 236 if( pstmt.execute() ) { // 6.1.0.0 (2014/12/26) refactoring 237 try( ResultSet resultSet = pstmt.getResultSet() ) { 238// rtn = DBUtil.resultToArray( resultSet,useHeader ); // 4.3.7.0 (2009/06/01) 239 rtn = resultToArray( resultSet,useHeader ); // 4.3.7.0 (2009/06/01) // 8.5.4.2 (2024/01/12) PMD 7.0.0 UnnecessaryFullyQualifiedName 240 } 241 } 242 // 6.3.6.1 (2015/08/28) 検索・登録関係なく、commit() する。 243 tran.commit(); // 5.1.9.0 (2010/08/01) Transaction 対応 244 } 245 } 246 catch( final SQLException ex ) { 247 tran.rollback(); // 5.1.9.0 (2010/08/01) Transaction 対応 248 final String errMsg = ex.getMessage() + ":" + ex.getSQLState() + CR 249 + "SQL=[" + stmt + "]" + CR 250 + "ARG=[" + StringUtil.array2csv( args ) + "]" + CR 251 + "DBID=[" + dbid + "]" + CR; 252 throw new OgRuntimeException( errMsg,ex ); 253 } 254 return rtn; 255 } 256 257 /** 258 * 初期データベースに接続して、CallableStatement(PL/SQL)を実行します(互換性確保のため残しています)。 259 * ステートメントと引数により、CallableStatement クエリーを実行します。 260 * 結果は、ステータスとエラーメッセージを返します。便宜的に、String配列に 261 * 設定して返します。 262 * ステートメント文字列には、{ call PLSQL( ?,?,?・・・ ) } となります。 263 * 第一引数、第二引数は、OUT属性で、結果(STATUS)とエラー時の内容(ERR_CODE)を返します。 264 * 第三引数以降の ? には、オブジェクトの引数配列 が順に割り当てられます。 265 * 266 * @og.rev 3.8.0.0 (2005/06/07) 新規追加 267 * @og.rev 3.8.7.0 (2006/12/15) アクセスログ取得の為、ApplicationInfoオブジェクトを設定 268 * @og.rev 4.0.0.0 (2007/10/10) dbid の初期値を、"DEFAULT" から null に変更 269 * @og.rev 5.1.9.0 (2010/08/01) Transaction 対応します。 270 * @og.rev 5.3.7.0 (2011/07/01) TransactionReal の引数変更 271 * @og.rev 5.3.8.0 (2011/08/01) TransactionReal と close() 処理をセットで実行する。 272 * @og.rev 6.3.6.1 (2015/08/28) Transaction でAutoCloseableを使用したtry-with-resources構築に対応。 273 * 274 * @param stmt ステートメント文字列 275 * @param args オブジェクトの引数配列 276 * @param appInfo アプリ情報オブジェクト 277 * 278 * @return 実行結果([0]=ステータス、[1]=エラーメッセージ 279 */ 280 public static String[] dbCallExecute( final String stmt ,final String[] args, final ApplicationInfo appInfo ) { 281 try( Transaction tran = new TransactionReal( appInfo ) ) { 282 return dbCallExecute( stmt ,args, tran, null ); 283 } 284 } 285 286 /** 287 * 初期データベースに接続して、CallableStatement(PL/SQL)を実行します(Transaction 対応)。 288 * ステートメントと引数により、CallableStatement クエリーを実行します。 289 * 結果は、ステータスとエラーメッセージを返します。便宜的に、String配列に 290 * 設定して返します。 291 * ステートメント文字列には、{ call PLSQL( ?,?,?・・・ ) } となります。 292 * 第一引数、第二引数は、OUT属性で、結果(STATUS)とエラー時の内容(ERR_CODE)を返します。 293 * 第三引数以降の ? には、オブジェクトの引数配列 が順に割り当てられます。 294 * 295 * @og.rev 5.1.9.0 (2010/08/01) 新規作成 Transaction 対応 296 * 297 * @param stmt ステートメント文字列 298 * @param args オブジェクトの引数配列 299 * @param tran Transactionオブジェクト 300 * 301 * @return 実行結果([0]=ステータス、[1]=エラーメッセージ 302 */ 303 public static String[] dbCallExecute( final String stmt ,final String[] args, final Transaction tran ) { 304 return dbCallExecute( stmt ,args, tran, null ); 305 } 306 307 /** 308 * 検索するデータベースを指定して、CallableStatement(PL/SQL)を実行します(互換性確保のため残しています)。 309 * ステートメントと引数により、CallableStatement クエリーを実行します。 310 * 結果は、ステータスとエラーメッセージを返します。便宜的に、String配列に 311 * 設定して返します。 312 * ステートメント文字列には、{ call PLSQL( ?,?,?・・・ ) } となります。 313 * 第一引数、第二引数は、OUT属性で、結果(STATUS)とエラー時の内容(ERR_CODE)を返します。 314 * 第三引数以降の ? には、オブジェクトの引数配列 が順に割り当てられます。 315 * 検索するデータベースは、DEFAULT です。 316 * 317 * @og.rev 3.8.0.0 (2005/06/07) 新規追加 318 * @og.rev 3.8.7.0 (2006/12/15) アクセスログ取得の為、ApplicationInfoオブジェクトを設定 319 * @og.rev 4.0.0.1 (2007/12/03) try ~ catch ~ finally をきちんと行う。 320 * @og.rev 5.1.9.0 (2010/08/01) Transaction 対応します。 321 * @og.rev 5.3.7.0 (2011/07/01) TransactionReal の引数変更 322 * @og.rev 5.3.8.0 (2011/08/01) TransactionReal と close() 処理をセットで実行する。 323 * @og.rev 6.3.6.1 (2015/08/28) Transaction でAutoCloseableを使用したtry-with-resources構築に対応。 324 * 325 * @param stmt ステートメント文字列 326 * @param args オブジェクトの引数配列 327 * @param appInfo アプリ情報オブジェクト 328 * @param dbid 接続先ID 329 * 330 * @return 実行結果([0]=ステータス、[1]=エラーメッセージ 331 */ 332 public static String[] dbCallExecute( final String stmt ,final String[] args, final ApplicationInfo appInfo ,final String dbid ) { 333 try( Transaction tran = new TransactionReal( appInfo ) ) { 334 return dbCallExecute( stmt ,args, tran, dbid ); 335 } 336 } 337 338 /** 339 * 検索するデータベースを指定して、CallableStatement(PL/SQL)を実行します(Transaction 対応)。 340 * ステートメントと引数により、CallableStatement クエリーを実行します。 341 * 結果は、ステータスとエラーメッセージを返します。便宜的に、String配列に 342 * 設定して返します。 343 * ステートメント文字列には、{ call PLSQL( ?,?,?・・・ ) } となります。 344 * 第一引数、第二引数は、OUT属性で、結果(STATUS)とエラー時の内容(ERR_CODE)を返します。 345 * 第三引数以降の ? には、オブジェクトの引数配列 が順に割り当てられます。 346 * 検索するデータベースは、DEFAULT です。 347 * 348 * @og.rev 5.1.9.0 (2010/08/01) 新規作成 Transaction 対応 349 * @og.rev 5.3.8.0 (2011/08/01) Transaction を引数で受け取った場合は、close() しない。 350 * @og.rev 6.4.2.1 (2016/02/05) try-with-resources 文で記述。 351 * @og.rev 6.9.3.0 (2018/03/26) データ検索時のフェッチサイズを設定。 352 * 353 * @param stmt ステートメント文字列 354 * @param args オブジェクトの引数配列 355 * @param tran Transactionオブジェクト 356 * @param dbid 接続先ID 357 * 358 * @return 実行結果([0]=ステータス、[1]=エラーメッセージ 359 */ 360 public static String[] dbCallExecute( final String stmt ,final String[] args, final Transaction tran ,final String dbid ) { 361 362 final String[] rtn = new String[2] ; // 8.5.4.2 (2024/01/12) PMD 7.0.0 LocalVariableCouldBeFinal 363 364 try { 365 final Connection conn = tran.getConnection( dbid ); // 5.1.9.0 (2010/08/01) Transaction 対応 366 try( CallableStatement callStmt = conn.prepareCall( stmt ) ) { 367 callStmt.setFetchSize( DB_FETCH_SIZE ); // 6.9.3.0 (2018/03/26) データ検索時のフェッチサイズ 368 369 callStmt.registerOutParameter( 1, Types.INTEGER ); 370 callStmt.registerOutParameter( 2, Types.VARCHAR ); 371 if( args != null ) { 372 for( int i=0; i<args.length; i++ ) { 373 callStmt.setObject( i+3,args[i] ); 374 } 375 } 376 callStmt.execute(); 377 378 rtn[0] = String.valueOf( callStmt.getInt(1) ); // 結果ステータス 379 rtn[1] = callStmt.getString(2); // 内容(エラーメッセージ) 380 381 tran.commit(); // 5.1.9.0 (2010/08/01) Transaction 対応 382 } 383 } 384 catch( final SQLException ex ) { 385 tran.rollback(); // 5.1.9.0 (2010/08/01) Transaction 対応 386 final String errMsg = ex.getMessage() + ":" + ex.getSQLState() + CR 387 + "SQL=[" + stmt + "]" + CR 388 + "ARG=[" + StringUtil.array2csv( args ) + "]" + CR 389 + "DBID=[" + dbid + "]" + CR; 390 throw new OgRuntimeException( errMsg,ex ); 391 } 392 return rtn; 393 } 394 395 /** 396 * SQL文の実行結果において、データの件数を取得します(互換性確保のため残しています)。 397 * ステートメントと引数により、Prepared クエリーの検索を実行します。 398 * 結果は、件数を数値で返します。 399 * あくまで、存在チェックに必要な処理のみ行っているため、通常の検索より高速です。 400 * 401 * @og.rev 3.5.0.0 (2003/09/17) 新規作成 402 * @og.rev 3.8.0.8 (2005/10/03) エラーメッセージの出力順をメッセージ+Queryに変更します。 403 * @og.rev 3.8.7.0 (2006/12/15) アクセスログ取得の為、ApplicationInfoオブジェクトを設定 404 * @og.rev 4.0.0.1 (2007/12/03) try ~ catch ~ finally をきちんと行う。 405 * @og.rev 5.1.2.0 (2010/01/01) setObject に ParameterMetaData の getParameterType を渡す。(PostgreSQL対応) 406 * @og.rev 5.1.9.0 (2010/08/01) Transaction 対応します。 407 * @og.rev 5.3.7.0 (2011/07/01) TransactionReal の引数変更 408 * @og.rev 5.3.8.0 (2011/08/01) TransactionReal と close() 処理をセットで実行する。 409 * @og.rev 6.3.6.1 (2015/08/28) Transaction でAutoCloseableを使用したtry-with-resources構築に対応。 410 * 411 * @param stmt ステートメント文字列 412 * @param args オブジェクトの引数配列 413 * @param appInfo アプリ情報オブジェクト 414 * @param dbid 接続先ID 415 * 416 * @return 検索結果(データの件数) 417 */ 418 public static int dbExist( final String stmt ,final String[] args, final ApplicationInfo appInfo , final String dbid ) { 419 try( Transaction tran = new TransactionReal( appInfo ) ) { 420 return dbExist( stmt ,args, tran , dbid ); 421 } 422 } 423 424 /** 425 * SQL文の実行結果において、データの件数を取得します(Transaction 対応)。 426 * ステートメントと引数により、Prepared クエリーの検索を実行します。 427 * 結果は、件数を数値で返します。 428 * あくまで、存在チェックに必要な処理のみ行っているため、通常の検索より高速です。 429 * 430 * @og.rev 5.1.9.0 (2010/08/01) 新規作成 Transaction 対応 431 * @og.rev 5.3.8.0 (2011/08/01) Transaction を引数で受け取った場合は、close() しない。 432 * @og.rev 5.3.8.0 (2011/08/01) useParamMetaData を ConnectionFactory経由で取得。(PostgreSQL対応)、setNull 対応 433 * @og.rev 6.4.2.1 (2016/02/05) try-with-resources 文で記述。 434 * @og.rev 6.9.3.0 (2018/03/26) データ検索時のフェッチサイズを設定。 7.2.9.1 (2020/10/23) サイズ指定しない。 435 * @og.rev 8.5.6.1 (2024/03/29) PMD 7.0.0 Finding duplicated code with CPD 436 * 437 * @param stmt ステートメント文字列 438 * @param args オブジェクトの引数配列 439 * @param tran Transactionオブジェクト 440 * @param dbid 接続先ID 441 * 442 * @return 検索結果(データの件数) 443 */ 444 public static int dbExist( final String stmt ,final String[] args, final Transaction tran , final String dbid ) { 445 int rtnCnt = -1; 446 447 try { 448 final Connection conn = tran.getConnection( dbid ); // 5.1.9.0 (2010/08/01) Transaction 対応 449 try( PreparedStatement pstmt = conn.prepareStatement( stmt ) ) { 450// pstmt.setFetchSize( DB_FETCH_SIZE ); // 6.9.3.0 (2018/03/26) データ検索時のフェッチサイズ 451 // 8.5.6.1 (2024/03/29) PMD 7.0.0 Finding duplicated code with CPD 452 pstmtValueSet( pstmt, args, dbid ); 453// if( args != null ) { 454// // 5.1.2.0 (2010/01/01) setObject に ParameterMetaData の getParameterType を渡す。(PostgreSQL対応) 455// final boolean useParamMetaData = ConnectionFactory.useParameterMetaData( dbid ); // 5.3.8.0 (2011/08/01) 456// if( useParamMetaData ) { 457// final ParameterMetaData pMeta = pstmt.getParameterMetaData(); 458// for( int i=0; i<args.length; i++ ) { 459// final int type = pMeta.getParameterType( i+1 ); 460// // 5.3.8.0 (2011/08/01) setNull 対応 461// final String val = args[i]; 462// if( val == null || val.isEmpty() ) { 463// pstmt.setNull( i+1, type ); 464// } 465// else { 466// pstmt.setObject( i+1, val, type ); 467// } 468// } 469// } 470// else { 471// for( int i=0; i<args.length; i++ ) { 472// pstmt.setObject( i+1,args[i] ); 473// } 474// } 475// } 476 try( ResultSet resultSet = pstmt.executeQuery() ) { 477 if( resultSet.next() ) { 478 rtnCnt = resultSet.getInt(1); 479 } 480 } 481 } 482 tran.commit(); // 6.3.6.1 (2015/08/28) 検索・登録関係なく、commit() する。 483 } 484 catch( final SQLException ex ) { 485 tran.rollback(); // 6.3.6.1 (2015/08/28) 検索・登録関係なく処理する。 486 final String errMsg = ex.getMessage() + ":" + ex.getSQLState() + CR 487 + "SQL=[" + stmt + "]" + CR 488 + "ARG=[" + StringUtil.array2csv( args ) + "]" + CR 489 + "DBID=[" + dbid + "]" + CR; 490 throw new OgRuntimeException( errMsg,ex ); // 3.5.5.4 (2004/04/15) 引数の並び順変更 491 } 492 return rtnCnt; 493 } 494 495 /** 496 * PreparedStatement の 変数設定を行います。 497 * 498 * ParameterMetaData の使用可否に応じてセット方法を切り替えます。 499 * これは、ソース上の同一処理をメソッド化したものです。 500 * 501 * @og.rev 8.5.6.1 (2024/03/29) PMD 7.0.0 Finding duplicated code with CPD 502 * 503 * @param pstmt PreparedStatementオブジェクト 504 * @param args オブジェクトの引数配列 505 * @param dbid 接続先ID 506 * 507 * @throws java.sql.SQLException データベース・アクセス・エラーが発生した場合 508 */ 509 private static void pstmtValueSet( final PreparedStatement pstmt, final String[] args, final String dbid ) throws SQLException { 510 // 6.4.3.2 (2016/02/19) args が null でなく、length==0 でない場合のみ、処理する。 511 if( args != null && args.length > 0 ) { 512 // 5.1.1.0 (2009/11/11) setObject に ParameterMetaData の getParameterType を渡す。(PostgreSQL対応) 513 final boolean useParamMetaData = ConnectionFactory.useParameterMetaData( dbid ); // 5.3.8.0 (2011/08/01) 514 if( useParamMetaData ) { 515 final ParameterMetaData pMeta = pstmt.getParameterMetaData(); 516 for( int i=0; i<args.length; i++ ) { 517 final int type = pMeta.getParameterType( i+1 ); 518 // 5.3.8.0 (2011/08/01) setNull 対応 519 final String val = args[i]; 520 if( val == null || val.isEmpty() ) { 521 pstmt.setNull( i+1, type ); 522 } 523 else { 524 pstmt.setObject( i+1, val, type ); 525 } 526 } 527 } 528 else { 529 for( int i=0; i<args.length; i++ ) { 530 pstmt.setObject( i+1,args[i] ); 531 } 532 } 533 } 534 } 535 536 /** 537 * ResultSet より、結果の文字列配列を作成します。 538 * 539 * 結果は、すべて文字列に変換されて格納されます。 540 * 移動したメソッドで使われているのでこれも移動 541 * 542 * @og.rev 3.1.0.0 (2003/03/20) Vector を使用している箇所で、非同期でも構わない箇所を、ArrayList に置換え。 543 * @og.rev 3.8.0.8 (2005/10/03) エラーメッセージの出力順をメッセージ+Queryに変更します。 544 * @og.rev 4.0.0.0 (2005/01/31) private ⇒ public、ヘッダー情報の取得有無フラグの追加 545 * @og.rev 5.6.7.0 (2013/07/27) CLOB 対応 546 * @og.rev 6.0.4.0 (2014/11/28) ResultSetValue クラスで、ResultSet から値を取得する処理を行う。 547 * 548 * @param resultSet ResultSetオブジェクト 549 * @param useHeader true:ヘッダーを第一行に含める/false:含めない 550 * 551 * @return ResultSetの検索結果配列 552 * @throws java.sql.SQLException データベース・アクセス・エラーが発生した場合 553 */ 554 public static String[][] resultToArray( final ResultSet resultSet,final boolean useHeader ) throws SQLException { 555// final ArrayList<String[]> data = new ArrayList<>(); 556 final List<String[]> data = new ArrayList<>(); // 8.5.4.2 (2024/01/12) PMD 7.0.0 LooseCoupling 557 558 final ResultSetValue rsv = new ResultSetValue( resultSet ); 559 560 if( useHeader ) { data.add( rsv.getNames() ); } 561 562 while( rsv.next() ) { 563 data.add( rsv.getValues() ); 564 } 565 566 final int size = data.size(); 567 final String[][] rtn = new String[size][]; // 8.5.4.2 (2024/01/12) PMD 7.0.0 LocalVariableCouldBeFinal 568 for( int i=0; i<size; i++ ) { 569 rtn[i] = data.get(i); 570 } 571 572 return rtn; 573 } 574 575 /** 576 * コネクションオブジェクトからデータベースのProductNameを取り出します。 577 * ProductName は、小文字化して返します。 578 * また、処理エラーが発生した場合は、"none" を返します。 579 * ここでは、SQLException は、発生させません。 580 * 581 * @og.rev 5.6.7.0 (2013/07/27) 新規追加 582 * @og.rev 5.6.7.4 (2013/08/30) ProductNameの小文字化対応 583 * @og.rev 6.7.4.2 (2017/02/24) ProductNameの大文字化対応 584 * 585 * @param conn コネクションオブジェクト 586 * 587 * @return データベースのProductName 588 */ 589 public static String getProductName( final Connection conn ) { 590 String dbName ; 591 try { 592 dbName = conn.getMetaData().getDatabaseProductName().toUpperCase( Locale.JAPAN ); // 6.7.4.2 (2017/02/24) 593 } 594 catch( final SQLException ex ) { 595 dbName = "none"; 596 } 597 return dbName ; 598 } 599}