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     */
016    package org.opengion.fukurou.db;
017    
018    import org.opengion.fukurou.util.StringUtil;
019    import org.opengion.fukurou.util.ApplicationInfo;
020    import org.opengion.fukurou.util.Closer;
021    import org.opengion.fukurou.model.Formatter;
022    import org.opengion.fukurou.model.ArrayDataModel;
023    
024    import java.sql.Connection;
025    import java.sql.PreparedStatement;
026    import java.sql.ParameterMetaData;
027    import java.sql.SQLException;
028    
029    import 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     */
047    public 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  インサーãƒ?QL
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  アãƒ??ãƒ??ãƒ?QL
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  ãƒ?ƒªーãƒ?QL
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    }