    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シートは、{&#064;カラム} で記述されており、このカラムの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のシートを指定します。シート番号は、０から始まります。
    353         * この、データEXCELシート(SHEETREF)は、単一数、カンマ結合、LAST文字 で指定します。
    354         * 単一数：雛形シートと１対１で対応するデータ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}