    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 org.opengion.fukurou.util.StringUtil;
    019import org.opengion.fukurou.util.ApplicationInfo;
    020import org.opengion.fukurou.util.Closer;
    021import org.opengion.fukurou.model.Formatter;
    022import org.opengion.fukurou.model.ArrayDataModel;
    023
    024import java.sql.Connection;
    025import java.sql.PreparedStatement;
    026import java.sql.ParameterMetaData;
    027import java.sql.SQLException;
    028
    029import java.util.Arrays;
    030
    031/**
    032 * DBTableModel インターフェースを継承した TableModel の実装クラスです。
    033 * sql文を execute( query ) する事により,データベースを検索した結果を
    034 * DBTableModel に割り当てます。
    035 *
    036 * メソッドを宣言しています
    037 * DBTableModel インターフェースは，データベースの検索結果(Resultset)をラップする
    038 * インターフェースとして使用して下さい。
    039 *
    040 * @og.rev 5.2.2.0 (2010/11/01) パッケージ移動(hayabusa.db ⇒ fukurou.db)
    041 * @og.group ＤＢ/Shell制御
    042 *
    043 * @version  4.0
    044 * @author   Kazuhiko Hasegawa
    045 * @since    JDK5.0,
    046 */
    047public class DBSimpleTable {
    048
    049        /** システム依存の改行記号をセットします。 */
    050        private static final String CR = System.getProperty("line.separator");
    051
    052        private final String[]  names ;                         // データ配列に対応するカラム配列(names)
    053        private String[]        keys            = null;         // 登録に使用するカラムキー配列(keys)
    054        private int[]           keysNo          = null;         // 登録に使用するカラムキー配列番号
    055        private String          table           = null;         // 登録テーブル名
    056        private String          where           = null;         // where 条件式[カラム名]を含む
    057        private int[]           whereNo         = null;         // [カラム名]に対応するデータ配列番号
    058        private String[]        constrain       = null;         // key に対応した制約条件
    059
    060        private String          connID          = null;         // 登録に使用するコネクションID
    061        private boolean         useWhere        = false;        // where が設定されると true にセットされます。
    062
    063        private Connection      conn            = null;
    064        private PreparedStatement pstmt = null;
    065        private ParameterMetaData pMeta = null;         // 5.1.2.0 (2010/01/01) setObject に、Type を渡す。(PostgreSQL対応)
    066        private String          query           = null;         // エラーメッセージ用の変数
    067        private int                     execCnt         = 0;
    068        private ApplicationInfo appInfo  = null;        // 3.8.7.0 (2006/12/15)
    069        private boolean useParamMetaData = false;       // 5.1.2.0 (2010/01/01) setObject に、Type を渡す。(PostgreSQL対応)
    070
    071        /**
    072         * データ配列のカラム名称配列を指定してオブジェクトを構築します。
    073         *
    074         * @param       nm      カラム名称配列
    075         * @throws RuntimeException tbl が null の場合
    076         */
    077        public DBSimpleTable( final String[] nm ) {
    078                if( nm == null ) {
    079                        String errMsg = "データ配列のカラム名称に null は設定できません。";
    080                        throw new RuntimeException( errMsg );
    081                }
    082
    083                names = new String[nm.length];
    084                System.arraycopy( nm,0,names,0,names.length );
    085        }
    086
    087        /**
    088         * 登録に使用するカラムキー配列(keys)を登録します。
    089         *
    090         * 引数のkey配列が null の場合は、names と同じカラム名称配列(names)が使用されます。
    091         * キー配列(keys)は、一度しか登録できません。また、addConstrain等のメソッド
    092         * 呼び出しを先に実行すると、カラム名称配列(names)が設定されてしまう為、
    093         * その後にこのメソッドを呼び出すとエラーが発生します。
    094         *
    095         * @param       key     登録カラム名称配列
    096         * @see         #addConstrain( String ,String )
    097         * @throws RuntimeException すでに キー配列(keys)が登録済み/作成済みの場合
    098         */
    099        public void setKeys( final String[] key ) {
    100                if( keys != null ) {
    101                        String errMsg = "すでに キー配列(keys)が登録済みです。";
    102                        throw new RuntimeException( errMsg );
    103                }
    104
    105                if( key != null ) {
    106                        int size = key.length;
    107                        keys = new String[size];
    108                        System.arraycopy( key,0,keys,0,size );
    109
    110                        constrain = new String[size];
    111                        Arrays.fill( constrain,"?" );
    112
    113                        keysNo = new int[size];
    114                        for( int i=0; i<size; i++ ) {
    115                                int address = findAddress( names,keys[i] );
    116                                if( address >= 0 ) {
    117                                        keysNo[i] = address;
    118                                }
    119                                else {
    120                                        String errMsg = "指定の key は、カラム配列(names)に存在しません"
    121                                                                + " key[" + i + "]=" + key[i]
    122                                                                + " names=" + StringUtil.array2csv( names ) ;
    123                                        throw new RuntimeException( errMsg );
    124                                }
    125                        }
    126                }
    127        }
    128
    129        /**
    130         * カラム名称配列(names)と同じキー配列(keys)を作成します。
    131         *
    132         * これは、キー配列(keys) が作成されなかった場合の処理です。
    133         * keys が null の場合のみ、処理を実行します。
    134         *
    135         * @see         #setKeys( String[] )
    136         */
    137        private void makeKeys() {
    138                // キー配列(keys) が未設定の場合は、カラム名称配列(names)が設定されます。
    139                if( keys == null ) {
    140                        keys = names;
    141                        int size = keys.length;
    142
    143                        constrain = new String[size];
    144                        Arrays.fill( constrain,"?" );
    145
    146                        keysNo = new int[size];
    147                        for( int i=0; i<size; i++ ) {
    148                                keysNo[i] = i;
    149                        }
    150                }
    151        }
    152
    153        /**
    154         * Insert/Update/Delete 時の登録するテーブル名
    155         *
    156         * @param       tbl     テーブル名
    157         * @throws RuntimeException tbl が null の場合
    158         */
    159        public void setTable( final String tbl ) {
    160                if( tbl == null ) {
    161                        String errMsg = "table に null は設定できません。";               // 5.1.8.0 (2010/07/01) errMsg 修正
    162                        throw new RuntimeException( errMsg );
    163                }
    164
    165                table = tbl;
    166        }
    167
    168        /**
    169         * データベースの接続先IDを設定します。
    170         *
    171         * @param       conn    接続先ID
    172         */
    173        public void setConnectionID( final String conn ) {
    174                connID = conn;
    175        }
    176
    177        /**
    178         * アクセスログ取得の為,ApplicationInfoオブジェクトを設定します。
    179         *
    180         * @og.rev 3.8.7.0 (2006/12/15) 新規追加
    181         *
    182         * @param   appInfo アプリ情報オブジェクト
    183         */
    184        public void setApplicationInfo( final ApplicationInfo appInfo ) {
    185                this.appInfo = appInfo;
    186        }
    187
    188        /**
    189         * Insert/Update/Delete 時の PreparedStatement の引数(?)制約
    190         *
    191         * 制約条件(val)は、そのまま引数に使用されます。通常、? で表される
    192         * パラメータに、文字長を制限する場合、SUBSTRB( ?,1,100 ) という
    193         * val 変数を与えます。
    194         * また、キー一つに対して、値を複数登録したい場合にも、使用できます。
    195         * 例えば、NVAL( ?,? ) のような場合、キー一つに値２つを割り当てます。
    196         * 値配列の並び順は、キー配列(keys)に対する(?の個数)に対応します。
    197         * 注意：カラム名称配列(names)ではありません。また、先にキー配列(keys)を登録
    198         * しておかないと、キー配列登録時にエラーが発生します。
    199         * 制約条件は、処理するQUERYに対して適用されますので、
    200         * key または、val が null の場合は、RuntimeException を Throwします。
    201         *
    202         * @param       key     制約をかけるキー
    203         * @param       val     制約条件式
    204         * @see         #setKeys( String[] )
    205         * @throws RuntimeException key または、val が null の場合
    206         */
    207        public void addConstrain( final String key,final String val ) {
    208                if( key == null || val == null ) {
    209                        String errMsg = "key または、val に null は設定できません。"
    210                                                + " key=[" + key + "] , val=[" + val + "]" ;
    211                        throw new RuntimeException( errMsg );
    212                }
    213
    214                // キー配列(keys)が未設定(null)の場合は、カラム名称配列(names)を割り当てます。
    215                if( keys == null ) { makeKeys(); }
    216
    217                // 制約条件のアドレスは、カラム名称配列(names)でなく、キー配列(keys)を使用します。
    218                int address = findAddress( keys,key );
    219                if( address >= 0 ) {
    220                        constrain[address] = val;
    221                }
    222                else {
    223                        String errMsg = "指定の key は、キー配列(keys)に存在しません"
    224                                                + " key=[" + key + "] , val=[" + val + "]"
    225                                                + " keys=" + StringUtil.array2csv( keys ) ;
    226                        throw new RuntimeException( errMsg );
    227                }
    228        }
    229
    230        /**
    231         * Update/Delete 時のキーとなるWHERE 条件のカラム名を設定します。
    232         *
    233         * 通常の WHERE 句の書き方と同じで、カラム配列(names)に対応する設定値(values)の値を
    234         * 割り当てたい箇所に[カラム名] を記述します。文字列の場合、設定値をセットする
    235         * ときに、シングルコーテーションを使用しますが、[カラム名]で指定する場合は、
    236         * その前後に、(')シングルコーテーションは、不要です。
    237         * WHERE条件は、登録に使用するキー配列(keys)に現れない条件で行を特定することがありますので
    238         * カラム名称配列(names)を元にカラム名のアドレスを求めます。
    239         * [カラム名]は、? に置き換えて、PreparedStatement として、実行される形式に変換されます。
    240         * 例：FGJ='1' and CLM=[CLM] and SYSTEM_ID in ([SYSID],'**')
    241         *
    242         * @og.rev 4.3.4.0 (2008/12/01) キー配列(keys)が未設定(null)の場合は、カラム名称配列(names)を割り当てる
    243         * @og.rev 5.0.2.0 (2009/11/01) バグ修正(keysはデータセットのキーなので、where句のカラムに含まれて入いるわけではない)
    244         *
    245         * @param  wh WHERE条件のカラム名
    246         * @throws RuntimeException [カラム名]がカラム配列(names)に存在しない場合
    247         */
    248        public void setWhere( final String wh ) {
    249
    250                if( wh != null ) {
    251                        // キー配列(keys)が未設定(null)の場合は、カラム名称配列(names)を割り当てます。
    252//                      if( keys == null ) { makeKeys(); }
    253
    254//                      ArrayDataModel data = new ArrayDataModel( keys );
    255                        // 5.0.2.0 (2009/11/01)
    256                        ArrayDataModel data = new ArrayDataModel( names );
    257                        Formatter format = new Formatter( data );
    258                        format.setFormat( wh );
    259                        where = format.getQueryFormatString();
    260                        whereNo = format.getClmNos();
    261
    262//                      StringBuilder buf = new StringBuilder( wh.length() );
    263//
    264//                      // 注意：[ と ] が隣接したケースでは処理できません。
    265//                      String wh2 = wh.replace( '[',']' );
    266//                      CSVTokenizer token = new CSVTokenizer( wh2,']',false );
    267//                      int cnt = token.countTokens() / 2 ;
    268////                    String format = null;
    269//                      whereNo = new int[ cnt ];
    270//                      for( int i=0; i<cnt; i++ ) {
    271////                            format = token.nextToken();
    272////                            buf.append( format);
    273//                              buf.append( token.nextToken() );        // format
    274//                              String clm = token.nextToken();
    275//                              // カラム名称配列(names)を元にカラム名のアドレスを求めます。
    276//                              int address = findAddress( names,clm );
    277//                              if( address >= 0 ) { whereNo[i] = address; }
    278//                              else {
    279//                                      String errMsg = "[" + clm + "]が、カラム配列(names)に存在しません。" + CR
    280//                                                              + " names=" + StringUtil.array2csv( names );
    281//                                      throw new RuntimeException( errMsg );
    282//                              }
    283//                              buf.append( "?" );              // [カラム] を ? に置き換え
    284//                      }
    285////                    format = token.nextToken();
    286////                    buf.append( format );
    287//                      buf.append( token.nextToken() );        // format
    288//
    289//                      where = buf.toString();
    290                }
    291                else {
    292                        where = null;
    293                }
    294        }
    295
    296        /**
    297         * データをインサートする場合に使用するSQL文を作成します。
    298         *
    299         * @return  インサートSQL
    300         */
    301        private String getInsertSQL() {
    302                // キー配列(keys)が未設定(null)の場合は、カラム名称配列(names)を割り当てます。
    303                if( keys == null ) { makeKeys(); }
    304
    305                StringBuilder sql = new StringBuilder();
    306                sql.append( "INSERT INTO " ).append( table );
    307                sql.append( " ( " );
    308                sql.append( keys[0] );
    309                for( int i=1; i<keys.length; i++ ) {
    310                        sql.append( "," ).append( keys[i] );
    311                }
    312                sql.append( " ) VALUES ( " );
    313                sql.append( constrain[0] );
    314                for( int i=1; i<keys.length; i++ ) {
    315                        sql.append( "," ).append( constrain[i] );
    316                }
    317                sql.append( " )" );
    318
    319                useWhere = false;
    320
    321                return sql.toString();
    322        }
    323
    324        /**
    325         * データをアップデートする場合に使用するSQL文を作成します。
    326         *
    327         * @return  アップデートSQL
    328         */
    329        private String getUpdateSQL() {
    330                // キー配列(keys)が未設定(null)の場合は、カラム名称配列(names)を割り当てます。
    331                if( keys == null ) { makeKeys(); }
    332
    333                StringBuilder sql = new StringBuilder();
    334                sql.append( "UPDATE " ).append( table ).append( " SET " );
    335                sql.append( keys[0] ).append( " = " ).append( constrain[0] );
    336
    337                for( int i=1; i<keys.length; i++ ) {
    338                        sql.append( " , " );
    339                        sql.append( keys[i] ).append( " = " ).append( constrain[i] );
    340                }
    341
    342                if( where != null && where.length() > 0 ) {
    343                        sql.append( " WHERE " ).append( where );
    344                        useWhere = true;
    345                }
    346                else {
    347                        useWhere = false;
    348                }
    349
    350                return sql.toString();
    351        }
    352
    353        /**
    354         * データをデリートする場合に使用するSQL文を作成します。
    355         *
    356         * @og.rev 5.0.2.0 (2009/11/01) バグ修正(削除時はkeysは必要ない)
    357         *
    358         * @return  デリートSQL
    359         */
    360        private String getDeleteSQL() {
    361                // キー配列(keys)が未設定(null)の場合は、カラム名称配列(names)を割り当てます。
    362//              if( keys == null ) { makeKeys(); }
    363                // 5.0.2.0 (2009/11/01)
    364                keys = new String[0];
    365
    366                StringBuilder sql = new StringBuilder();
    367                sql.append( "DELETE FROM " ).append( table );
    368
    369                if( where != null && where.length() > 0 ) {
    370                        sql.append( " WHERE " ).append( where );
    371                        useWhere = true;
    372                }
    373                else {
    374                        useWhere = false;
    375                }
    376
    377                return sql.toString();
    378        }
    379
    380        /**
    381         * Insert 処理の開始を宣言します。
    382         * 内部的に、コネクションを接続して、PreparedStatementオブジェクトを作成します。
    383         * このメソッドと、close() メソッドは必ずセットで処理してください。
    384         *
    385         * @og.rev 3.8.7.0 (2006/12/15) アクセスログ取得の為,ApplicationInfoオブジェクトを設定
    386         * @og.rev 5.1.2.0 (2010/01/01) setObject に ParameterMetaData の getParameterType を渡す。(PostgreSQL対応)
    387         * @og.rev 5.3.8.0 (2011/08/01) useParamMetaData を ConnectionFactory経由で取得。(PostgreSQL対応)
    388         *
    389         * @throws SQLException Connection のオープンに失敗した場合
    390         */
    391        public void startInsert() throws SQLException {
    392                execCnt = 0;
    393                query = getInsertSQL();
    394                conn  = ConnectionFactory.connection( connID,appInfo );
    395                pstmt = conn.prepareStatement( query );
    396                // 5.1.2.0 (2010/01/01) setObject に ParameterMetaData の getParameterType を渡す。(PostgreSQL対応)
    397//              useParamMetaData = ApplicationInfo.useParameterMetaData( conn );
    398                useParamMetaData = ConnectionFactory.useParameterMetaData( connID );    // 5.3.8.0 (2011/08/01)
    399                if( useParamMetaData ) {
    400                        pMeta = pstmt.getParameterMetaData();
    401                }
    402        }
    403
    404        /**
    405         * Update 処理の開始を宣言します。
    406         * 内部的に、コネクションを接続して、PreparedStatementオブジェクトを作成します。
    407         * このメソッドと、close() メソッドは必ずセットで処理してください。
    408         *
    409         * @og.rev 3.8.7.0 (2006/12/15) アクセスログ取得の為,ApplicationInfoオブジェクトを設定
    410         * @og.rev 5.1.2.0 (2010/01/01) setObject に ParameterMetaData の getParameterType を渡す。(PostgreSQL対応)
    411         * @og.rev 5.3.8.0 (2011/08/01) useParamMetaData を ConnectionFactory経由で取得。(PostgreSQL対応)
    412         *
    413         * @throws SQLException Connection のオープンに失敗した場合
    414         */
    415        public void startUpdate() throws SQLException {
    416                execCnt = 0;
    417                query = getUpdateSQL();
    418                conn  = ConnectionFactory.connection( connID,appInfo );
    419                pstmt = conn.prepareStatement( query );
    420                // 5.1.2.0 (2010/01/01) setObject に ParameterMetaData の getParameterType を渡す。(PostgreSQL対応)
    421//              useParamMetaData = ApplicationInfo.useParameterMetaData( conn );
    422                useParamMetaData = ConnectionFactory.useParameterMetaData( connID );    // 5.3.8.0 (2011/08/01)
    423                if( useParamMetaData ) {
    424                        pMeta = pstmt.getParameterMetaData();
    425                }
    426        }
    427
    428        /**
    429         * Delete 処理の開始を宣言します。
    430         * 内部的に、コネクションを接続して、PreparedStatementオブジェクトを作成します。
    431         * このメソッドと、close() メソッドは必ずセットで処理してください。
    432         *
    433         * @og.rev 3.8.7.0 (2006/12/15) アクセスログ取得の為,ApplicationInfoオブジェクトを設定
    434         * @og.rev 5.1.2.0 (2010/01/01) setObject に ParameterMetaData の getParameterType を渡す。(PostgreSQL対応)
    435         * @og.rev 5.3.8.0 (2011/08/01) useParamMetaData を ConnectionFactory経由で取得。(PostgreSQL対応)
    436         *
    437         * @throws SQLException Connection のオープンに失敗した場合
    438         */
    439        public void startDelete() throws SQLException {
    440                execCnt = 0;
    441                query = getDeleteSQL();
    442                conn  = ConnectionFactory.connection( connID,appInfo );
    443                pstmt = conn.prepareStatement( query );
    444                // 5.1.2.0 (2010/01/01) setObject に ParameterMetaData の getParameterType を渡す。(PostgreSQL対応)
    445//              useParamMetaData = ApplicationInfo.useParameterMetaData( conn );
    446                useParamMetaData = ConnectionFactory.useParameterMetaData( connID );    // 5.3.8.0 (2011/08/01)
    447                if( useParamMetaData ) {
    448                        pMeta = pstmt.getParameterMetaData();
    449                }
    450        }
    451
    452        /**
    453         * データ配列を渡して実際のDB処理を実行します。
    454         *
    455         * この処理の前に、startXXXX をコールしておき、INSER,UPDATE,DELETEのどの
    456         * 処理を行うか、宣言しておく必要があります。
    457         * 戻り値は、この処理での処理件数です。
    458         * 最終件数は、close( boolean ) 時に取得します。
    459         *
    460         * @og.rev 4.0.0.0 (2007/11/28) SQLException をきちんと伝播させます。
    461         * @og.rev 5.1.2.0 (2010/01/01) setObject に ParameterMetaData の getParameterType を渡す。(PostgreSQL対応)
    462         * @og.rev 5.3.8.0 (2011/08/01) useParamMetaData 時の setNull 対応(PostgreSQL対応)
    463         *
    464         * @param       values  カラム配列(names) に対応する設定値配列
    465         *
    466         * @return      ここでの処理件数
    467         *
    468         * @see    #close( boolean )
    469         * @throws SQLException Connection のクロースに失敗した場合
    470         * @throws RuntimeException Connection DB処理の実行に失敗した場合
    471         */
    472        public int execute( final String[] values ) throws SQLException {
    473                final int cnt;
    474                try {
    475                        int clmNo = 1;  // JDBC のカラム番号は、１から始まる。
    476
    477                        // 5.1.2.0 (2010/01/01) setObject に ParameterMetaData の getParameterType を渡す。(PostgreSQL対応)
    478                        if( useParamMetaData ) {
    479                                // keys に値を割り当てます。
    480                                for( int i=0; i<keys.length; i++ ) {
    481                                        int type = pMeta.getParameterType( clmNo );
    482                                        // 5.3.8.0 (2011/08/01) setNull 対応
    483//                                      pstmt.setObject( clmNo++,values[keysNo[i]],type );
    484                                        String val = values[keysNo[i]];
    485                                        if( val == null || val.isEmpty() ) {
    486                                                pstmt.setNull( clmNo++, type );
    487                                        }
    488                                        else {
    489                                                pstmt.setObject( clmNo++,val,type );
    490                                        }
    491                                }
    492
    493                                // where 条件を使用する場合は、値を割り当てます。
    494                                if( useWhere ) {
    495                                        for( int i=0; i<whereNo.length; i++ ) {
    496                                                int type = pMeta.getParameterType( clmNo );
    497                                                // 5.3.8.0 (2011/08/01) setNull 対応
    498//                                              pstmt.setObject( clmNo++,values[whereNo[i]],type );
    499                                                String val = values[whereNo[i]];
    500                                                if( val == null || val.isEmpty() ) {
    501                                                        pstmt.setNull( clmNo++, type );
    502                                                }
    503                                                else {
    504                                                        pstmt.setObject( clmNo++,val,type );
    505                                                }
    506                                        }
    507                                }
    508                        }
    509                        else {
    510                                // keys に値を割り当てます。
    511                                for( int i=0; i<keys.length; i++ ) {
    512                                        pstmt.setObject( clmNo++,values[keysNo[i]] );
    513                                }
    514
    515                                // where 条件を使用する場合は、値を割り当てます。
    516                                if( useWhere ) {
    517                                        for( int i=0; i<whereNo.length; i++ ) {
    518                                                pstmt.setObject( clmNo++,values[whereNo[i]] );
    519                                        }
    520                                }
    521                        }
    522
    523                        cnt = pstmt.executeUpdate();
    524                        execCnt += cnt;
    525                }
    526                catch (SQLException ex) {
    527                        Closer.stmtClose( pstmt );
    528                        pMeta = null;           // 5.1.2.0 (2010/01/01)
    529                        if( conn != null ) {
    530                                conn.rollback();
    531                                ConnectionFactory.remove( conn,connID );
    532                                conn = null;
    533                        }
    534                        String errMsg = "DB処理の実行に失敗しました。" + CR
    535                                                + " query=[" + query + "]" + CR
    536                                                + " values=" + StringUtil.array2csv( values );
    537//                      throw new RuntimeException( errMsg );
    538                        throw new RuntimeException( errMsg ,ex );
    539                }
    540                return cnt;
    541        }
    542
    543        /**
    544         * DB処理をクロースします。
    545         *
    546         * 引数には、commit させる場合は、true を、rollback させる場合は、false をセットします。
    547         * 戻り値は、今まで処理された合計データ件数です。
    548         * この処理は、SQLException を内部で RuntimeException に変換している為、catch 節は
    549         * 不要ですが、必ず finally 節で呼び出してください。そうしないと、リソースリークの
    550         * 原因になります。
    551         *
    552         * @og.rev 5.1.2.0 (2010/01/01) pMeta のクリア
    553         *
    554         * @param  commitFlag コミットフラグ [true:commitする/false:rollbacする]
    555         *
    556         * @return      今までの合計処理件数
    557         */
    558        public int close( final boolean commitFlag ) {
    559                if( conn != null ) {
    560                        try {
    561                                if( commitFlag ) {      conn.commit();  }
    562                                else {                          conn.rollback(); }
    563                        }
    564                        catch (SQLException ex) {
    565                                ConnectionFactory.remove( conn,connID );
    566                                conn = null;
    567                                String errMsg = "DB処理を確定(COMMIT)できませんでした。" + CR
    568                                                        + " query=[" + query + "]" + CR ;
    569                                throw new RuntimeException( errMsg,ex );
    570                        }
    571                        finally {
    572                                Closer.stmtClose( pstmt );
    573                                pMeta = null;           // 5.1.2.0 (2010/01/01)
    574                                ConnectionFactory.close( conn,connID );
    575                                conn = null;
    576                        }
    577                }
    578
    579                return execCnt;
    580        }
    581
    582        /**
    583         * 文字列配列中の値とマッチするアドレスを検索します。
    584         * 文字列配列がソートされていない為、バイナリサーチが使えません。よって、
    585         * 総当りでループ検索しています。
    586         * 総数が多い場合は、遅くなる為、マップにセットして使用することを検討ください。
    587         *
    588         * @param       data    ターゲットの文字列配列中
    589         * @param       key     検索する文字列
    590         *
    591         * @return  ターゲットの添え字(存在しない場合は、-1)
    592         */
    593        private int findAddress( final String[] data,final String key ) {
    594                int address = -1;
    595                if( data != null && key != null ) {
    596                        for( int i=0; i<data.length; i++ ) {
    597                                if( key.equalsIgnoreCase( data[i] ) ) {
    598                                        address = i;
    599                                        break;
    600                                }
    601                        }
    602                }
    603                return address;
    604        }
    605}