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.report; 017 018import static org.opengion.fukurou.system.HybsConst.CR ; // 6.1.0.0 (2014/12/26) 019import static org.opengion.fukurou.system.HybsConst.BUFFER_MIDDLE; // 6.4.2.1 (2016/02/05) 020import static org.opengion.fukurou.system.HybsConst.DB_FETCH_SIZE; // 6.9.4.1 (2018/04/09) 021 022import org.opengion.fukurou.system.ThrowUtil ; // 6.4.2.0 (2016/01/29) 023import org.opengion.fukurou.util.StringUtil; 024import org.opengion.fukurou.util.FileUtil; 025import org.opengion.fukurou.db.ApplicationInfo; 026import org.opengion.fukurou.system.Closer; 027import org.opengion.fukurou.db.ConnectionFactory; 028import org.opengion.fukurou.db.DBUtil; // 5.5.5.1 (2012/08/07) 029import org.opengion.hayabusa.common.HybsSystem; 030import org.opengion.hayabusa.common.HybsSystemException; 031 032import java.io.File; 033import java.io.IOException; 034import java.util.List; 035import java.util.Arrays; 036 037import java.sql.Connection; 038import java.sql.PreparedStatement; 039import java.sql.SQLException; 040 041/** 042 * 【EXCEL取込】雛形EXCELシートと、データEXCELシートから、指定のDBにデータを登録するクラスクラスです。 043 * 雛形EXCELシートは、{@カラム} で記述されており、このカラムのEXCEL上のセルの位置を元に、 044 * データEXCELシートから所定のデータを読みこみ、雛形明細定義(GE57)で指定のテーブルに 045 * 抜き出したデータを登録します。 046 * 雛形明細定義(GE57)では、システムID+帳票ID+シート番号をキーに、読み取る対応シートや 047 * シート毎にヘッダーテーブル、明細テーブルの指定、繰返必須カラムのしていなどにより、 048 * 読取る方式と、書き込むテーブルを指定します。 049 * 050 * @og.rev 3.8.0.0 (2005/06/07) 新規追加 051 * @og.group 帳票システム 052 * 053 * @version 4.0 054 * @author Kazuhiko Hasegawa 055 * @since JDK5.0, 056 */ 057public class ExcelInsert { 058 private final StringBuilder errMsg ; 059 060 // DBTableReport に対して設定する情報 061 private final String EXCELIN ; // EXCEL ファイルの取込DIR ファイル名は、要求番号.xls 062 063 // 受け渡し変数 064 private final String SYSTEM_ID ; 065 private final String YKNO ; 066 private final String LISTID ; 067 private final boolean DEBUG ; // 3.8.5.0 (2006/03/06) デバッグ用のフラグを追加 068 069 // GE54,GE57 帳票定義、明細情報 070 // 6.3.9.0 (2015/11/06) Variables should start with a lowercase character(PMD) 071 private String modelDIR ; // GE54 雛形EXCELディレクトリ 072 private String modelFILE ; // GE54 雛形EXCELファイル名 073 private String[] sheetNO ; // GE57 雛形EXCELシート番号 074 private String[] sheetREF ; // GE57 データEXCELシート番号 075 private String[] headDBID ; // GE57 ヘッダーテーブル 076 private String[] bodyDBID ; // GE57 明細テーブル 077 private String[] loopCLM ; // GE57 繰返必須カラム名 078 private ExcelLayout layout ; 079 080 // GE54,GE57 の帳票定義情報を取得するSQL文です。 081 private static final String GE54_GE57_SELECT = 082 "SELECT A.MODELDIR,A.MODELFILE,B.SHEETNO,B.SHEETREF,B.HEADDBID,B.BODYDBID,B.LOOPCLM" + 083 " FROM GE54 A INNER JOIN GE57 B" + 084 " ON A.SYSTEM_ID = B.SYSTEM_ID AND A.LISTID = B.LISTID" + 085 " WHERE A.FGJ = '1' AND B.FGJ = '1'" + 086 " AND A.SYSTEM_ID = ?" + 087 " AND A.LISTID = ?" + 088 " ORDER BY B.SHEETNO" ; 089 090 /** コネクションにアプリケーション情報を追記するかどうか指定 */ 091 public static final boolean USE_DB_APPLICATION_INFO = HybsSystem.sysBool( "USE_DB_APPLICATION_INFO" ) ; 092 093 // 3.8.7.0 (2006/12/15) アクセスログ取得の為,ApplicationInfoオブジェクトを設定 094 private final ApplicationInfo appInfo; 095 private final String DBID = HybsSystem.sys( "RESOURCE_DBID" ); // 5.5.5.1 (2012/08/07) リソース系DBID 付け忘れ対応 096 097 /** 098 * コンストラクター 099 * 引数を受けとって、インスタンスを作成します。 100 * 101 * @og.rev 3.8.7.0 (2006/12/15) アクセスログ取得の為,ApplicationInfoオブジェクトを設定 102 * 103 * @param system_id システムID 104 * @param ykno 要求番号 105 * @param listId 帳票ID 106 * @param excelinDir 出力ディレクトリ 107 * @param debug デバッグフラグ 108 */ 109 public ExcelInsert( final String system_id, final String ykno, final String listId, final String excelinDir, final boolean debug ) { 110 SYSTEM_ID = system_id; 111 YKNO = ykno; 112 LISTID = listId; 113 EXCELIN = excelinDir; 114 DEBUG = debug; 115 errMsg = new StringBuilder( BUFFER_MIDDLE ); 116 117 // 3.8.7.0 (2006/12/15) アクセスログ取得の為,ApplicationInfoオブジェクトを設定 118 if( USE_DB_APPLICATION_INFO ) { 119 appInfo = new ApplicationInfo(); 120 // ユーザーID,IPアドレス,ホスト名 121 appInfo.setClientInfo( SYSTEM_ID,HybsSystem.HOST_ADRS,HybsSystem.HOST_NAME ); 122 // 画面ID,操作,プログラムID 123 appInfo.setModuleInfo( "ExcelInsert",YKNO,LISTID ); 124 } 125 else { 126 appInfo = null; 127 } 128 } 129 130 /** 131 * 変換処理を実行します。 132 * 133 * @og.rev 3.8.0.9 (2005/10/17) エラーメッセージ強化 134 * 135 * @return 結果 [true:正常/false:異常] 136 */ 137 public boolean execute() { 138 System.out.print( "ExcelInsert Started ... " ); 139 boolean flag ; 140 141 try { 142 // 初期化 GE54,GE57 帳票定義マスタより必要な情報を取得します。 143 flag = initialDataSet(); 144 if( flag ) { System.out.print( "INIT," ); } 145 146 // 雛型ファイルの存在チェックを行います。 147 // 3.5.4.9 (2004/02/25) 存在チェックエラー(原因不明)の暫定対応 148 File templateExcel = null; 149 if( flag ) { 150 templateExcel = FileUtil.checkFile( modelDIR, modelFILE + ".xls" ); 151 flag = templateExcel != null ; // チェックの結果が null なら、見つからなかった。 152 // 3.8.0.9 (2005/10/17) エラーメッセージ強化 153 if( flag ) { System.out.print( "MDL IN," ); } 154 else { 155 errMsg.append( "ExcelInsert MODELFILE Not Found Error!" ).append( CR ); 156 errMsg.append( "==============================" ).append( CR ); 157 errMsg.append( "MODELDIR=" ).append( modelDIR ).append( CR ) ; 158 errMsg.append( "MODELFILE=" ).append( modelFILE ).append( ".xls" ) ; 159 errMsg.append( CR ) ; 160 } 161 } 162 163 // EXCELデータファイルの存在チェックを行います。 164 File inputExcel = null; 165 if( flag ) { 166 inputExcel = FileUtil.checkFile( EXCELIN, YKNO + ".xls" ); 167 flag = inputExcel != null ; // チェックの結果が null なら、見つからなかった。 168 // 3.8.0.9 (2005/10/17) エラーメッセージ強化 169 if( flag ) { System.out.print( "XLS IN," ); } 170 else { 171 errMsg.append( "ExcelInsert EXCELIN Not Found Error!" ).append( CR ); 172 errMsg.append( "==============================" ).append( CR ); 173 errMsg.append( "DIR=" ).append( EXCELIN ).append( CR ) ; 174 errMsg.append( "FILE=" ).append( YKNO ).append( ".xls" ) ; 175 errMsg.append( CR ) ; 176 } 177 } 178 179 // 雛形ファイルより、処理対象行列を読み取ります。 180 if( flag ) { 181 flag = getModelData( templateExcel ); 182 if( flag ) { System.out.print( "MDL DT," ); } 183 } 184 185 // EXCELデータファイルを読取り、データベースに書き込みます。 186 if( flag ) { 187 flag = readAndInsertDB( inputExcel ); 188 if( flag ) { System.out.print( "IN DB," ); } 189 } 190 } 191 catch( final RuntimeException ex ) { 192 errMsg.append( "ExcelInsert Execute Exception Error!" ).append( CR ) 193 .append( "==============================" ).append( CR ) 194 .append( ThrowUtil.ogStackTrace( ex ) ).append( CR ) ; // 6.4.2.0 (2016/01/29) 195 flag = false; 196 } 197 198 System.out.println( "End." ); 199 return flag ; 200 } 201 202 /** 203 * 初期データセットを行います。 204 * ここでは、GE54,GE57 テーブルより必要な情報を取得します。 205 * 206 * @og.rev 3.8.7.0 (2006/12/15) アクセスログ取得の為,ApplicationInfoオブジェクトを設定 207 * @og.rev 5.5.5.1 (2012/08/07) リソース系DBID 付け忘れ対策 208 * 209 * @return 結果 [true:正常/false:異常] 210 */ 211 private boolean initialDataSet() { 212 final String[] args = new String[] { SYSTEM_ID,LISTID }; 213 // A.MODELDIR,A.MODELFILE,B.SHEETNO,B.SHEETREF,B.HEADDBID,B.BODYDBID,B.LOOPCLM 214 final String[][] vals = DBUtil.dbExecute( GE54_GE57_SELECT,args,appInfo, DBID ); // 3.8.7.0 (2006/12/15) 215 if( vals == null || vals.length == 0 ) { 216 errMsg.append( "Data does not exist in GE54 table." ).append( CR ) 217 .append( "==============================" ).append( CR ) 218 .append( "SYSTEM_ID=[" ).append( SYSTEM_ID ) 219 .append( "] , LISTID=[" ).append( LISTID ) 220 .append( ']' ).append( CR ); // 6.0.2.5 (2014/10/31) char を append する。 221 return false; 222 } 223 224 modelDIR = StringUtil.nval( vals[0][0],modelDIR ); 225 modelFILE = StringUtil.nval( vals[0][1],modelFILE ); 226 227 if( modelDIR == null || modelDIR.isEmpty() || 228 modelFILE == null || modelFILE.isEmpty() ) { 229 errMsg.append( "MODELDIR and MODELFILE is necessary in GE54 table." ).append( CR ) 230 .append( "==============================" ).append( CR ) 231 .append( "SYSTEM_ID=[" ).append( SYSTEM_ID ) 232 .append( "] , LISTID=[" ).append( LISTID ) 233 .append( "] , MODELDIR=[" ).append( modelDIR ) 234 .append( "] , MODELFILE=[" ).append( modelFILE ) 235 .append( "] " ).append( CR ); 236 return false; 237 } 238 239 final int maxRow = vals.length; // 先の条件判断で、最低 1 件以上存在する。 240 sheetNO = new String[maxRow]; 241 sheetREF = new String[maxRow]; 242 headDBID = new String[maxRow]; 243 bodyDBID = new String[maxRow]; 244 loopCLM = new String[maxRow]; 245 246 for( int row=0; row<maxRow; row++ ) { 247 sheetNO[row] = StringUtil.nval( vals[row][2],null ); 248 sheetREF[row] = StringUtil.nval( vals[row][3],null ); 249 headDBID[row] = StringUtil.nval( vals[row][4],null ); 250 bodyDBID[row] = StringUtil.nval( vals[row][5],null ); 251 loopCLM[row] = StringUtil.nval( vals[row][6],null ); 252 253 // SHEETNO と SHEETREF は、どちら『も』必須 254 // HEADDBID と BODYDBID は、どちら『か』必須 255 if( sheetNO[row] == null || sheetREF[row] == null || headDBID[row] == null && bodyDBID[row] == null ) { // 6.9.7.0 (2018/05/14) PMD Useless parentheses. 256 errMsg.append( "SHEETNO と SHEETREF は、どちら『も』必須" ).append( CR ) 257 .append( "HEADDBID と BODYDBID は、どちら『か』必須" ).append( CR ) 258 .append( "==============================" ).append( CR ) 259 .append( "SYSTEM_ID=[" ).append( SYSTEM_ID ) 260 .append( "] , LISTID=[" ).append( LISTID ) 261 .append( "] , SHEETNO=[" ).append( sheetNO[row] ) 262 .append( "] , SHEETREF=[" ).append( sheetREF[row] ) 263 .append( "] , HEADDBID=[" ).append( headDBID[row] ) 264 .append( "] , BODYDBID=[" ).append( bodyDBID[row] ) 265 .append( "] " ).append( CR ); 266 return false; 267 } 268 } 269 270 return true; 271 } 272 273 /** 274 * 雛形ファイルより、対象行列を読み取ります。 275 * 276 * @og.rev 6.4.2.0 (2016/01/29) StringUtil#stringStackTrace(Throwable) を、ThrowUtil#ogStackTrace(Throwable) に置き換え。 277 * 278 * @param file 雛形ファイル 279 * 280 * @return 結果 [true:正常/false:異常] 281 */ 282 private boolean getModelData( final File file ) { 283 try { 284 layout = HybsHSSFListener.makeExcelLayout( file,false ); 285 } 286 catch( final IOException ex ) { 287 errMsg.append( "Template Excel File can not ModelData." ).append( CR ); 288 errMsg.append( "==============================" ).append( CR ); 289 errMsg.append( "File=" ).append( file.getAbsolutePath() ); 290 errMsg.append( ThrowUtil.ogStackTrace( ex ) ); // 6.4.2.0 (2016/01/29) 291 errMsg.append( CR ); 292 return false; 293 } 294 295 return true; 296 } 297 298 /** 299 * EXCELを読取り、データベースに書き込みます。 300 * 301 * @og.rev 3.8.7.0 (2006/12/15) アクセスログ取得の為,ApplicationInfoオブジェクトを設定 302 * 303 * @param file EXCELファイル 304 * 305 * @return 結果 [true:正常/false:異常] 306 */ 307 private boolean readAndInsertDB( final File file ) { 308 309 final ExcelDataPickup pickup = new ExcelDataPickup( layout,file,DEBUG ); 310 311 // 実際のデータシートの枚数 312 final int sheetSize = pickup.getSheetSize(); 313 // SHEETREF に対して、実際に割り当てなおしたシート対応 314 final int[] reference = makeSheetReference( sheetSize,sheetREF ); 315 316 final DatabaseExecute exec = new DatabaseExecute(); 317 exec.setApplicationInfo( appInfo ); // 3.8.7.0 (2006/12/15) 318 final int ykno = Integer.parseInt(YKNO) ; 319 for( int shNo=0; shNo<sheetSize; shNo++ ) { 320 final int ref = reference[shNo]; 321 if( ref < 0 ) { continue; } // 処理対象外 322 323 pickup.execute( Integer.parseInt( sheetNO[ref] ),shNo,loopCLM[ref] ) ; 324 325 final String headerQuery = layout.getHeaderInsertQuery( headDBID[ref] ); 326 if( headerQuery != null ) { 327 exec.setStatement( headerQuery ); 328 329 final String[] headerData = layout.getHeaderInsertData( SYSTEM_ID,ykno,shNo ); 330 exec.dbExecute( headerData ); 331 } 332 333 final String bodyQuery = layout.getBodyInsertQuery( bodyDBID[ref] ); 334 if( bodyQuery != null ) { 335 exec.setStatement( bodyQuery ); 336 337 final List<String[]> bodyData = layout.getBodyInsertData( SYSTEM_ID,ykno,shNo ); 338 for( int j=0; j<bodyData.size(); j++ ) { 339 exec.dbExecute( bodyData.get(j) ); 340 } 341 } 342 } 343 exec.commit(); 344 pickup.close(); 345 346 return true; 347 } 348 349 /** 350 * GE57 に指定のSHEETNOとSHEETREF配列より、実際にアクセスするシート番号に対応したリファレンス配列を求めます。 351 * SHEETNO は、雛形EXCELの使用するシート番号を指定します。SHEETREFは、その雛形シートを 352 * 利用して処理するデータEXCELのシートを指定します。シート番号は、0から始まります。 353 * この、データEXCELシート(SHEETREF)は、単一数、カンマ結合、LAST文字 で指定します。 354 * 単一数:雛形シートと1対1で対応するデータEXCELシート番号 355 * カンマ結合:3,4,5 や、2,5 などの複数シートをひとつの雛形シートで処理する場合に設定します。 356 * LAST文字:5,LAST や LAST と記述することで、それ以降の全データシートを雛形シートで処理します。 357 * 358 * ここでは、SHEETREF配列 を実際のデータEXCELシート数分の配列に再配置し、その元のアドレスを 359 * 指すリファレンス情報を返します。 360 * このリファレンス情報を元に、SHEETNO,HEADDBID,BODYDBID,LOOPCLM などの元の配列にアクセスし、 361 * 設定値を取得してきます。 362 * 363 * 例) 364 * SHEETNO = { "1","2" ,"3","4" ,"6" }; 365 * SHEETREF = { "1","2,6","4","5,3","8,LAST" }; 366 * HEADDBID = { "A","B" ,"C","D" ,"E" }; 367 * データシート数=11 368 * 369 * i=[0] , No=[1], REF=[1] 370 * i=[1] , No=[2], REF=[2,6] 371 * i=[2] , No=[3], REF=[4] 372 * i=[3] , No=[4], REF=[5,3] 373 * i=[4] , No=[6], REF=[8,LAST] 374 * ========================= 375 * REF=[0] , Ref=[-1], SHEETNO[] = - , HEADDBID[] = - 376 * REF=[1] , Ref=[0], SHEETNO[[0]]=[1] , HEADDBID[[0]]=[A] 377 * REF=[2] , Ref=[1], SHEETNO[[1]]=[2] , HEADDBID[[1]]=[B] 378 * REF=[3] , Ref=[3], SHEETNO[[3]]=[4] , HEADDBID[[3]]=[D] 379 * REF=[4] , Ref=[2], SHEETNO[[2]]=[3] , HEADDBID[[2]]=[C] 380 * REF=[5] , Ref=[3], SHEETNO[[3]]=[4] , HEADDBID[[3]]=[D] 381 * REF=[6] , Ref=[1], SHEETNO[[1]]=[2] , HEADDBID[[1]]=[B] 382 * REF=[7] , Ref=[-1], SHEETNO[] = - , HEADDBID[] = - 383 * REF=[8] , Ref=[4], SHEETNO[[4]]=[6] , HEADDBID[[4]]=[E] 384 * REF=[9] , Ref=[4], SHEETNO[[4]]=[6] , HEADDBID[[4]]=[E] 385 * REF=[10] , Ref=[4], SHEETNO[[4]]=[6] , HEADDBID[[4]]=[E] 386 * 387 * @param size データシートの総件数 388 * @param sheetRef データEXCELシートの対応する配列(可変長引数)(単一数、カンマ結合、LAST文字 が使用可能) 389 * 390 * @return データ件数分に再配置した、雛形EXCELシート番号配列。使用しない場合は、-1 がセット。 391 */ 392 private int[] makeSheetReference( final int size,final String... sheetRef ) { 393 394 int[] reference = new int[size]; 395 Arrays.fill( reference ,-1 ); 396 397 int maxNo = -1; 398 for( int i=0; i<sheetRef.length; i++ ) { 399 final String[] temp = StringUtil.csv2Array( sheetRef[i] ); 400 for( int j=0; j<temp.length; j++ ) { 401 if( temp[j].equals( "LAST" ) ) { 402 for( int k=maxNo; k<size; k++ ) { 403 reference[k] = i ; 404 } 405 i=size; 406 break; 407 } 408 else { 409 final int no = Integer.parseInt(temp[j]) ; 410 if( no < size ) { 411 reference[no] = i ; 412 if( maxNo < no ) { maxNo = no+1; } 413 } 414 else { 415 final String errMsg = "データシートと雛形明細定義の対応ができません。" 416 + " データシート総件数=[" + size + "] " 417 + " sheetRef[" + i + "]=" + sheetRef[i] ; 418 throw new HybsSystemException( errMsg ); 419 } 420 } 421 } 422 } 423 return reference ; 424 } 425 426 /** 427 * エラーが存在した場合に、エラーメッセージを返します。 428 * 429 * @return エラーメッセージ String 430 * @og.rtnNotNull 431 */ 432 public String getErrMsg() { 433 return errMsg.toString(); 434 } 435 436 /** 437 * 連続した データベース処理を行う為の、管理処理クラスです。 438 * ExcelInsert でのコーディングを分けるためだけのクラスです。 439 * 440 * オブジェクト作成時に、DEFAULT 接続を内部にキープし、setStatement( String )で 441 * PreparedStatementオブジェクトを作成します。このメソッドを呼ぶまでは、 442 * 同じ PreparedStatementオブジェクトを使い続けます。 443 * dbExecute( String[] ) メソッドで、PreparedStatement に設定する引数配列をセットします。 444 * この段階では、commit も、PreparedStatementのclose も行いませんので、連続して、 445 * dbExecute( String[] ) メソッドを呼び出すことが可能です。 446 * 最後に、commit() で、Connection は、プールに返されます。 447 * 448 * エラー時は、rollback() して、Connection は、破棄されます。 449 * 450 * @og.rev 6.3.9.1 (2015/11/27) パッケージプライベートクラスを、private static final class に変更 451 * 452 * @og.group 帳票システム 453 * 454 * @version 4.0 455 * @author Kazuhiko Hasegawa 456 * @since JDK5.0, 457 */ 458 private static final class DatabaseExecute { 459// /** 6.9.3.0 (2018/03/26) データ検索時のフェッチサイズ {@value} */ 460// private static final int DB_FETCH_SIZE = HybsSystem.sysInt( "DB_FETCH_SIZE" ) ; 461 462 // 4.0.0.0 (2007/10/10) dbid の初期値を、"DEFAULT" から null に変更 463 private static final String DBID = null ; 464 465 private Connection conn ; 466 private PreparedStatement pstmt ; 467 private String tempSql ; // エラー時にSQL文を表示させる場合に使用します。 468 private ApplicationInfo appInfo ; 469 470 /** 471 * アクセスログ取得の為,ApplicationInfoオブジェクトを設定します。 472 * 473 * @og.rev 3.8.7.0 (2006/12/15) 新規追加 474 * 475 * @param appInfo ApplicationInfoオブジェクト 476 */ 477 public void setApplicationInfo( final ApplicationInfo appInfo ) { 478 this.appInfo = appInfo; 479 } 480 481 /** 482 * PreparedStatementオブジェクトを作成します。 483 * 次に、このメソッドを呼ぶまでは、同じ PreparedStatementオブジェクトを使い続けます。 484 * 485 * @og.rev 3.8.7.0 (2006/12/15) アクセスログ取得の為,ApplicationInfoオブジェクトを設定 486 * @og.rev 4.0.0.1 (2007/12/03) try ~ catch ~ finally をきちんと行う。 487 * @og.rev 6.9.3.0 (2018/03/26) データ検索時のフェッチサイズを設定。 488 * 489 * @param stmt ステートメント 490 */ 491 public void setStatement( final String stmt ) { 492 boolean errFlag = true ; 493 tempSql = stmt; 494 try { 495 // 3.8.7.0 (2006/12/15) アクセスログ取得の為,ApplicationInfoオブジェクトを設定 496 if( conn == null ) { conn = ConnectionFactory.connection( DBID,appInfo ); } 497 Closer.stmtClose( pstmt ); 498 pstmt = conn.prepareStatement( stmt ); 499 pstmt.setFetchSize( DB_FETCH_SIZE ); // 6.9.3.0 (2018/03/26) データ検索時のフェッチサイズ 500 errFlag = false ; 501 } 502 catch( final SQLException ex) { 503 final String errMsg = "Statement を作成できませんでした。" + CR 504 + "SQL=[" + stmt + "]" 505 + ex.getMessage() + ":" + ex.getSQLState() ; 506 throw new HybsSystemException( errMsg,ex ); 507 } 508 finally { 509 if( errFlag ) { errorFinally(); } 510 } 511 } 512 513 /** 514 * Connection を commit します。 515 * このオブジェクトを終了する最後に行います。 516 * 517 */ 518 public void commit() { 519 boolean errFlag = true ; 520 try { 521 conn.commit(); 522 errFlag = false ; 523 } 524 catch( final SQLException ex) { 525 Closer.rollback( conn ); 526 final String errMsg = "Connection をコミットできませんでした。" + CR 527 + ex.getMessage() + ":" + ex.getSQLState() ; 528 throw new HybsSystemException( errMsg,ex ); 529 } 530 finally { 531 Closer.stmtClose( pstmt ); 532 if( errFlag ) { ConnectionFactory.remove( conn,DBID ); } 533 else { ConnectionFactory.close( conn,DBID ); } 534 conn = null; 535 } 536 } 537 538 /** 539 * PreparedStatement に設定する引数配列をセットします。 540 * 541 * この段階では、commit も、PreparedStatementのclose も行いませんので、連続して、 542 * dbExecute( String[] ) メソッドを呼び出すことが可能です。 543 * 544 * @param args オブジェクトの引数配列(可変長引数) 545 */ 546 public void dbExecute( final String... args ) { 547 // System.out.println( StringUtil.array2csv( args ) ); 548 549 boolean errFlag = true ; 550 try { 551 for( int i=0; i<args.length; i++ ) { 552 pstmt.setString( i+1,args[i] ); 553 } 554 pstmt.execute(); 555 errFlag = false ; 556 } 557 catch( final SQLException ex) { 558 final String errMsg = "データベース処理を実行できませんでした。" + CR 559 + "ARGS=[" + StringUtil.array2csv( args ) + "]" + CR 560 + "SQL=[" + tempSql + "]" 561 + ex.getMessage() + ":" + ex.getSQLState() ; 562 throw new HybsSystemException( errMsg,ex ); 563 } 564 finally { 565 if( errFlag ) { errorFinally(); } 566 } 567 } 568 569 /** 570 * エラー発生時の処理 571 * 572 * PreparedStatement のクローズと、Connection の破棄を行います。 573 */ 574 private void errorFinally() { 575 Closer.stmtClose( pstmt ); 576 pstmt = null; 577 Closer.rollback( conn ); 578 ConnectionFactory.remove( conn,DBID ); 579 conn = null; 580 } 581 } 582}