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.process;
017    
018    import org.opengion.fukurou.util.Argument;
019    import org.opengion.fukurou.util.SystemParameter;
020    import org.opengion.fukurou.util.LogWriter;
021    import org.opengion.fukurou.util.HybsEntry ;
022    import org.opengion.fukurou.util.Closer;
023    import org.opengion.fukurou.model.Formatter;
024    import org.opengion.fukurou.db.ConnectionFactory;
025    
026    import java.util.Map ;
027    import java.util.LinkedHashMap ;
028    
029    import java.sql.Connection;
030    import java.sql.PreparedStatement;
031    import java.sql.ParameterMetaData;
032    import java.sql.SQLException;
033    
034    /**
035     * Process_DBMerge は、UPDATE と INSERT を指定し ãƒ??タベã?スを追åŠ?›´新
036     * する、ChainProcess インターフェースの実è£?‚¯ラスですã?
037     * 上æµ?プロセスチェインのãƒ??タは上流から下流へと渡されますã?)から
038     * 受け取っã�?LineModel をå?に、DBTableModel 形式ファイルをå?力しますã?
039     *
040     * ãƒ??タベã?ス接続å?等ã?、ParamProcess のサブクラス(Process_DBParam)に
041     * 設定された接ç¶?Connection)を使用しますã?
042     *
043     * 引数æ–?­—å?中にスペã?スを含ã‚??合ã?、ダブルコーãƒ??ション("") で括って下さã�??
044     * 引数æ–?­—å?の ã€?』ã?前後には、スペã?スは挟めません。å¿?�šã€?key=value の様に
045     * 繋げてくださいã€?
046     *
047     * SQLæ–?�«は、{@DATE.YMDH}等ã?シスãƒ?ƒ 変数が使用できますã?
048     *
049     * @og.formSample
050     *  Process_DBMerge -dbid=DBGE -insertTable=GE41
051     *
052     *   [ -dbid=DB接続ID           ] ??-dbid=DBGE (ä¾? Process_DBParam の -configFile でæŒ?®šすã‚?DBConfig.xml ファイルで規å®?
053     *   [ -update=検索SQLæ–?       ] ??-update="UPDATE GE41 SET NAME_JA = [NAME_JA],LABEL_NAME = [LABEL_NAME]
054     *                                         WHERE SYSTEM_ID = [SYSTEM_ID] AND CLM = [CLM]"
055     *   [ -updateFile=登録SQL?Œァ?²?? ] ??-updateFile=update.sql
056     *                                ??  -update ã‚?-updateFile が指定されなã�??合ã?、エラーですã?
057     *   [ -update_XXXX=固定å?      ] ??-update_SYSTEM_ID=GE
058     *                                     SQLæ–?¸­の{@XXXX}æ–?­—å?を指定ã?固定å?で置き換えますã?
059     *                                     WHERE SYSTEM_ID='{@SYSTEM_ID}' �WHERE SYSTEM_ID='GE'
060     *   [ -insertTable=登録??½°?Œ゙ルID ] ??INSERTæ–?‚’æŒ?®šするå?合ã?不要ã?INSERT する場合ã?ãƒ??ブルID
061     *   [ -insert=検索SQLæ–?       ] ??-insert="INSERT INTO GE41 (SYSTEM_ID,CLM,NAME_JA,LABEL_NAME)
062     *                                         VALUES ([SYSTEM_ID],[CLM],[NAME_JA],[LABEL_NAME])"
063     *   [ -insertFile=登録SQL?Œァ?²?? ] ??-insertFile=insert.sql
064     *                                ??  -insert ã‚?-insertFile ã‚??-table が指定されなã�??合ã?、エラーですã?
065     *   [ -insert_XXXX=固定å?      ] ??-insert_SYSTEM_ID=GE
066     *                                     SQLæ–?¸­の{@XXXX}æ–?­—å?を指定ã?固定å?で置き換えますã?
067     *                                     WHERE SYSTEM_ID='{@SYSTEM_ID}' �WHERE SYSTEM_ID='GE'
068     *   [ -const_XXXX=固定å?       ] ??-const_FGJ=1
069     *                                     LineModel のキー(const_ に続くæ–?­—å?)の値に、固定å?を設定しますã?
070     *                                     キーが異なれã?、è¤?•°のカラãƒ?��を指定できますã?
071     *   [ -commitCnt=commit処ç�?Œ‡定] ??æŒ?®š数毎にコミットを発行しますã?0 の場合ã?、終äº?�¾でコミットしませんã€?
072     *   [ -display=false|true      ] ??結果を標準å?力に表示する(true)かしなã�?false)ã�?初期値:false[表示しない])
073     *
074     * @version  4.0
075     * @author   Kazuhiko Hasegawa
076     * @since    JDK5.0,
077     */
078    public class Process_DBMerge extends AbstractProcess implements ChainProcess {
079            private static final String UPDATE_KEY  = "update_" ;
080            private static final String INSERT_KEY  = "insert_" ;
081            private static final String CNST_KEY    = "const_" ;
082    
083            private Connection      connection      = null;
084            private PreparedStatement insPstmt      = null ;
085            private PreparedStatement updPstmt      = null ;
086            private ParameterMetaData insPmeta      = null ;        // 5.1.2.0 (2010/01/01) setObject に、Type を渡すã?(PostgreSQL対å¿?
087            private ParameterMetaData updPmeta      = null ;        // 5.1.2.0 (2010/01/01) setObject に、Type を渡すã?(PostgreSQL対å¿?
088            private boolean useParamMetaData        = false;        // 5.1.2.0 (2010/01/01) setObject に、Type を渡すã?(PostgreSQL対å¿?
089    
090            private String          dbid            = null;
091            private String          insert          = null;
092            private String          update          = null;
093            private String          insertTable     = null;
094            private int[]           insClmNos       = null;         // insert 時ã?ファイルのヘッãƒ??のカラãƒ?•ª号
095            private int[]           updClmNos       = null;         // update 時ã?ファイルのヘッãƒ??のカラãƒ?•ª号
096            private int                     commitCnt       = 0;            // コミットするまとめ件数
097            private boolean         display         = false;        // 表示しなã�?
098    
099            private String[]        cnstClm         = null;         // 固定å?を設定するカラãƒ?��
100            private int[]           cnstClmNos      = null;         // 固定å?を設定するカラãƒ?•ª号
101            private String[]        constVal        = null;         // カラãƒ?•ª号に対応した固定å?
102    
103            private boolean         firstRow        = true;         // æœ??のä¸?¡Œ目
104            private int                     count           = 0;
105            private int                     insCount        = 0;
106            private int                     updCount        = 0;
107    
108            private static final Map<String,String> mustProparty   ;          // ?»プロパティ?½å¿??チェãƒ?‚¯用 Map
109            private static final Map<String,String> usableProparty ;          // ?»プロパティ?½整合æ?チェãƒ?‚¯ Map
110    
111            static {
112                    mustProparty = new LinkedHashMap<String,String>();
113    
114                    usableProparty = new LinkedHashMap<String,String>();
115                    usableProparty.put( "dbid",     "Process_DBParam の -configFile でæŒ?®šすã‚?DBConfig.xml ファイルで規å®? );
116                    usableProparty.put( "update",   "更新SQLæ–?sql or sqlFile å¿??)" +
117                                                                            CR + "ä¾? \"UPDATE GE41 " +
118                                                                            CR + "SET NAME_JA = [NAME_JA],LABEL_NAME = [LABEL_NAME] " +
119                                                                            CR + "WHERE SYSTEM_ID = [SYSTEM_ID] AND CLM = [CLM]\"" );
120                    usableProparty.put( "updateFile",       "更新SQLファイル(sql or sqlFile å¿??)ä¾? update.sql" );
121                    usableProparty.put( "update_",          "SQLæ–?¸­の{&#064;XXXX}æ–?­—å?を指定ã?固定å?で置き換えますã?" +
122                                                                            CR + "WHERE SYSTEM_ID='{&#064;SYSTEM_ID}' �WHERE SYSTEM_ID='GE'" );
123                    usableProparty.put( "insert",                   "登録SQLæ–?sql or sqlFile å¿??)" +
124                                                                            CR + "ä¾? \"INSERT INTO GE41 " +
125                                                                            CR + "(SYSTEM_ID,CLM,NAME_JA,LABEL_NAME) " +
126                                                                            CR + "VALUES ([SYSTEM_ID],[CLM],[NAME_JA],[LABEL_NAME])\"" );
127                    usableProparty.put( "insertFile",               "登録SQLファイル(sql or sqlFile å¿??)ä¾? insert.sql" );
128                    usableProparty.put( "insertTable",      "INSERT する場合ã?ãƒ??ブルID SQLæ–?‚’æŒ?®šするå?合ã?不要ã?" );
129                    usableProparty.put( "insert_",          "SQLæ–?¸­の{&#064;XXXX}æ–?­—å?を指定ã?固定å?で置き換えますã?" +
130                                                                            CR + "WHERE SYSTEM_ID='{&#064;SYSTEM_ID}' �WHERE SYSTEM_ID='GE'" );
131                    usableProparty.put( "const_",   "LineModel のキー(const_ に続くæ–?­—å?)の値に、固定å?ã‚? +
132                                                                            CR + "設定しますã?キーが異なれã?、è¤?•°のカラãƒ?��を指定できますã?" +
133                                                                            CR + "ä¾? -sql_SYSTEM_ID=GE" );
134                    usableProparty.put( "commitCnt",        "æŒ?®š数毎にコミットを発行しますã?" +
135                                                                            CR + "0 の場合ã?、終äº?�¾でコミットしません(初期値: 0)" );
136                    usableProparty.put( "display",  "結果を標準å?力に表示する(true)かしなã�?false)ã�? +
137                                                                                    CR + "(初期値:false:表示しなã�?" );
138            }
139    
140            /**
141             * ãƒ?ƒ•ォルトコンストラクターã€?
142             * こã?クラスは、動çš?½œæ?されますã?ãƒ?ƒ•ォルトコンストラクターでã€?
143             * super クラスに対して、å¿?¦�な初期化を行っておきますã?
144             *
145             */
146            public Process_DBMerge() {
147                    super( "org.opengion.fukurou.process.Process_DBMerge",mustProparty,usableProparty );
148            }
149    
150            /**
151             * プロセスの初期化を行いますã?初めにä¸?º¦ã�?�‘、呼び出されますã?
152             * 初期処ç�?ファイルオープンã€?¼¤?¢オープンç­?に使用しますã?
153             *
154             * @og.rev 5.1.2.0 (2010/01/01) setObject に ParameterMetaData の getParameterType を渡すã?(PostgreSQL対å¿?
155             * @og.rev 5.3.8.0 (2011/08/01) useParamMetaData ã‚?ConnectionFactory経由で取得ã?(PostgreSQL対å¿?
156             *
157             * @param   paramProcess ãƒ??タベã?スの接続å?æƒ??などを持ってã�?‚‹オブジェクãƒ?
158             */
159            public void init( final ParamProcess paramProcess ) {
160                    Argument arg = getArgument();
161    
162                    insertTable             = arg.getProparty("insertTable");
163                    update                  = arg.getFileProparty("update","updateFile",false);
164                    insert                  = arg.getFileProparty("insert","insertFile",false);
165                    commitCnt               = arg.getProparty("commitCnt",commitCnt);
166                    display                 = arg.getProparty("display",display);
167    
168                    dbid            = arg.getProparty("dbid");
169                    connection      = paramProcess.getConnection( dbid );
170                    // 5.1.2.0 (2010/01/01) setObject に ParameterMetaData の getParameterType を渡すã?(PostgreSQL対å¿?
171    //              useParamMetaData = ApplicationInfo.useParameterMetaData( connection );
172                    useParamMetaData = ConnectionFactory.useParameterMetaData( dbid );      // 5.3.8.0 (2011/08/01)
173    
174                    if( insert == null && insertTable == null ) {
175                            String errMsg = "insert またã?、insertFile を指定しなã�??合ã?、insertTable をå¿?�šæŒ?®šしてくださいã€?;
176                            throw new RuntimeException( errMsg );
177                    }
178    
179                    if( insert != null && insertTable != null ) {
180                            String errMsg = "insert またã?、insertFile と、insertTable は、両方同時にæŒ?®šできませんã€?"
181                                                                     + insert + "],[" + insertTable + "]";
182                            throw new RuntimeException( errMsg );
183                    }
184    
185                    // 3.8.0.1 (2005/06/17) {@DATE.XXXX} 変換処ç�??追åŠ?
186                    // {@DATE.YMDH} などのæ–?­—å?をã?yyyyMMddHHmmss 型ã?日付に置き換えますã?
187                    // SQLæ–?? {@XXXX} æ–?­—å?の固定å?への置き換ã�?
188                    HybsEntry[] entry       =arg.getEntrys(UPDATE_KEY);             // 配å?
189                    SystemParameter sysParam = new SystemParameter( update );
190                    update = sysParam.replace( entry );
191    
192                    if( insert != null ) {
193                            entry   =arg.getEntrys(INSERT_KEY);             // 配å?
194                            sysParam = new SystemParameter( insert );
195                            insert = sysParam.replace( entry );
196                    }
197    
198                    HybsEntry[] cnstKey = arg.getEntrys( CNST_KEY );                // 配å?
199                    int csize       = cnstKey.length;
200                    cnstClm         = new String[csize];
201                    constVal        = new String[csize];
202                    for( int i=0; i<csize; i++ ) {
203                            cnstClm[i]  = cnstKey[i].getKey();
204                            constVal[i] = cnstKey[i].getValue();
205                    }
206            }
207    
208            /**
209             * プロセスの終äº?‚’行いますã?æœ?¾Œにä¸?º¦ã�?�‘、呼び出されますã?
210             * 終äº??ç�?ファイルクローズã€?¼¤?¢クローズç­?に使用しますã?
211             *
212             * @og.rev 4.0.0.0 (2007/11/27) commit,rollback,remove 処ç�?‚’追åŠ?
213             * @og.rev 5.1.2.0 (2010/01/01) insPmeta , updPmeta のクリア
214             *
215             * @param   isOK トã?タルで、OKã�?�£たかどã�?�‹[true:成功/false:失敗]
216             */
217            public void end( final boolean isOK ) {
218                    boolean flag1 = Closer.stmtClose( updPstmt );
219                    updPstmt = null;
220                    boolean flag2 = Closer.stmtClose( insPstmt );
221                    insPstmt = null;
222    
223                    insPmeta        = null ;        // 5.1.2.0 (2010/01/01)
224                    updPmeta        = null ;        // 5.1.2.0 (2010/01/01)
225    
226                    // close に失敗してã�?‚‹のに commit しても良ã�??かï¼?
227                    if( isOK ) {
228                            Closer.commit( connection );
229                    }
230                    else {
231                            Closer.rollback( connection );
232                    }
233                    ConnectionFactory.remove( connection,dbid );
234    
235                    if( ! flag1 ) {
236                            String errMsg = "update スãƒ??トメントをクローズ出来ませんã€? + CR
237                                                            + " update=[" + update + "] , commit=[" + isOK + "]" ;
238                            throw new RuntimeException( errMsg );
239                    }
240    
241                    if( ! flag2 ) {
242                            String errMsg = "insert スãƒ??トメントをクローズ出来ませんã€? + CR
243                                                            + " insert=[" + insert + "] , commit=[" + isOK + "]" ;
244                            throw new RuntimeException( errMsg );
245                    }
246            }
247    
248            /**
249             * 引数の LineModel をå?ç�?�™るメソãƒ?ƒ‰ですã?
250             * 変換処ç�?¾Œã? LineModel を返しますã?
251             * 後続å?ç�?‚’行わなã�??å�?ãƒ??タのフィルタリングを行う場å�?はã€?
252             * null ãƒ??タを返しますã?つまりã?null ãƒ??タは、後続å?ç�?‚’行わなã�?
253             * フラグの代わりにも使用してã�?�¾すã?
254             * なおã?変換処ç�?¾Œã? LineModel と、オリジナルの LineModel がã?
255             * 同ä¸?�‹、コピã?(クローン)かã?、各処ç�?ƒ¡ソãƒ?ƒ‰å†?�§決めてã�?�¾すã?
256             * ドキュメントに明記されてã�?�ªã�??合ã?、副作用が問題になるå?合ã?ã€?
257             * å�??ç�?�”とに自åˆ?�§コピã?(クローン)して下さã�??
258             *
259             * @og.rev 5.1.2.0 (2010/01/01) setObject に ParameterMetaData の getParameterType を渡すã?(PostgreSQL対å¿?
260             * @og.rev 5.3.8.0 (2011/08/01) useParamMetaData  setNull 対å¿?PostgreSQL対å¿?
261             *
262             * @param       data ラインモãƒ?ƒ« オリジナルのLineModel
263             *
264             * @return      処ç�?¤‰換後ã?LineModel
265             */
266            public LineModel action( final LineModel data ) {
267                    count++ ;
268                    int updCnt = 0;
269                    try {
270                            if( firstRow ) {
271                                    makePrepareStatement( insertTable,data );
272    
273                                    int size   = cnstClm.length;
274                                    cnstClmNos = new int[size];
275                                    for( int i=0; i<size; i++ ) {
276                                            cnstClmNos[i] = data.getColumnNo( cnstClm[i] );
277                                    }
278    
279                                    firstRow = false;
280                            }
281    
282                            // 固定å?置き換えå?ç�?
283                            for( int j=0; j<cnstClmNos.length; j++ ) {
284                                    data.setValue( cnstClmNos[j],constVal[j] );
285                            }
286    
287                            // 5.1.2.0 (2010/01/01) setObject に ParameterMetaData の getParameterType を渡すã?(PostgreSQL対å¿?
288                            if( useParamMetaData ) {
289                                    for( int i=0; i<updClmNos.length; i++ ) {
290                                            int type = updPmeta.getParameterType( i+1 );
291                                            // 5.3.8.0 (2011/08/01) setNull 対å¿?
292    //                                      updPstmt.setObject( i+1,data.getValue(updClmNos[i]),type );
293                                            Object val = data.getValue(updClmNos[i]);
294                                            if( val == null || ( val instanceof String && ((String)val).isEmpty() ) ) {
295                                                    updPstmt.setNull( i+1, type );
296                                            }
297                                            else {
298                                                    updPstmt.setObject( i+1, val, type );
299                                            }
300                                    }
301                            }
302                            else {
303                                    for( int i=0; i<updClmNos.length; i++ ) {
304                                            updPstmt.setObject( i+1,data.getValue(updClmNos[i]) );
305                                    }
306                            }
307    
308                            updCnt = updPstmt.executeUpdate();
309                            if( updCnt == 0 ) {
310                                    // 5.1.2.0 (2010/01/01) setObject に ParameterMetaData の getParameterType を渡すã?(PostgreSQL対å¿?
311                                    if( useParamMetaData ) {
312                                            for( int i=0; i<insClmNos.length; i++ ) {
313                                                    int type = insPmeta.getParameterType( i+1 );
314                                                    // 5.3.8.0 (2011/08/01) setNull 対å¿?
315    //                                              insPstmt.setObject( i+1,data.getValue(insClmNos[i]),type );
316                                                    Object val = data.getValue(insClmNos[i]);
317                                                    if( val == null || ( val instanceof String && ((String)val).isEmpty() ) ) {
318                                                            insPstmt.setNull( i+1, type );
319                                                    }
320                                                    else {
321                                                            insPstmt.setObject( i+1, val, type );
322                                                    }
323                                            }
324                                    }
325                                    else {
326                                            for( int i=0; i<insClmNos.length; i++ ) {
327                                                    insPstmt.setObject( i+1,data.getValue(insClmNos[i]) );
328                                            }
329                                    }
330                                    int insCnt = insPstmt.executeUpdate();
331                                    if( insCnt == 0 ) {
332                                            String errMsg = "?‘件も追åŠ?�•れませんでしたã€? + CR
333                                                                    + " insert=[" + insert + "]" + CR
334                                                                    + "[" + data.getRowNo() + "]件目" + CR ;
335                                            throw new RuntimeException( errMsg );
336                                    }
337                                    insCount++ ;
338                            }
339                            else if( updCnt > 1 ) {
340                                    String errMsg = "è¤?•°行が同時に更新されましたã€?" + updCnt + "]件" + CR
341                                                            + " update=[" + update + "]" + CR
342                                                            + "[" + data.getRowNo() + "]件目" + CR ;
343                                    throw new RuntimeException( errMsg );
344                            }
345                            else {
346                                    updCount ++ ;
347                            }
348    
349                            if( commitCnt > 0 && ( count%commitCnt == 0 ) ) {
350                                    Closer.commit( connection );
351                            }
352                            if( display ) { printKey( count,updCnt,data ); }
353                    }
354                    catch (SQLException ex) {
355                            String errMsg = "登録処ç�?�§エラーが発生しましたã€? + CR
356                                                    + ((updCnt == 1) ?
357                                                                    " update=[" + update + "]"
358                                                            :       " insert=[" + insert + "]" + CR
359                                                                    + " insertTable=[" + insertTable + "]" )
360                                                    + CR
361                                                    + "[" + data.getRowNo() + "]件目" + CR
362                                                    + "errorCode=[" + ex.getErrorCode() + "] State=["
363                                                    + ex.getSQLState() + "]" + CR ;
364                            throw new RuntimeException( errMsg,ex );
365                    }
366                    return data;
367            }
368    
369            /**
370             * å†?ƒ¨で使用する PreparedStatement を作æ?しますã?
371             * 引数æŒ?®šã? SQL またã?、LineModel から作æ?した SQL より構築しますã?
372             *
373             * @og.rev 5.1.2.0 (2010/01/01) setObject に ParameterMetaData の getParameterType を渡すã?(PostgreSQL対å¿?
374             *
375             * @param       table   処ç�?¯¾象のãƒ??ブルID
376             * @param       data ラインモãƒ?ƒ« 処ç�?¯¾象のLineModel
377             */
378            private void makePrepareStatement( final String table,final LineModel data ) {
379                    if( insert == null ) {
380                            StringBuilder buf = new StringBuilder();
381                            String[] names = data.getNames();
382                            int size = names.length;
383    
384                            buf.append( "INSERT INTO " ).append( table ).append( " (" );
385                            buf.append( names[0] );
386                            for( int i=1; i<size; i++ ) {
387                                    buf.append( "," ).append( names[i] );
388                            }
389                            buf.append( " ) VALUES ( ?" );
390                            for( int i=1; i<size; i++ ) {
391                                    buf.append( ",?" );
392                            }
393                            buf.append( " )" );
394                            insert = buf.toString();
395    
396                            // カラãƒ?•ª号を設定しますã?
397                            insClmNos = new int[size];
398                            for( int i=0; i<size; i++ ) {
399                                    insClmNos[i] = i;
400                            }
401                    }
402                    else {
403                            Formatter format = new Formatter( data );
404                            format.setFormat( insert );
405                            insert = format.getQueryFormatString();
406                            insClmNos = format.getClmNos();
407                    }
408    
409                    Formatter format = new Formatter( data );
410                    format.setFormat( update );
411                    update = format.getQueryFormatString();
412                    updClmNos = format.getClmNos();
413    
414                    try {
415                            insPstmt = connection.prepareStatement( insert );
416                            updPstmt = connection.prepareStatement( update );
417                            // 5.1.2.0 (2010/01/01) setObject に ParameterMetaData の getParameterType を渡すã?(PostgreSQL対å¿?
418                            if( useParamMetaData ) {
419                                    insPmeta = insPstmt.getParameterMetaData();
420                                    updPmeta = updPstmt.getParameterMetaData();
421                            }
422                    }
423                    catch (SQLException ex) {
424                            String errMsg = "PreparedStatement を取得できませんでしたã€? + CR
425                                                    + "insert=[" + insert + "]" + CR
426                                                    + "update=[" + update + "]" + CR
427                                                    + "table=[" + table + "]" + CR
428                                                    + "nameLine=[" + data.nameLine() + "]" ;
429                            throw new RuntimeException( errMsg,ex );
430                    }
431            }
432    
433            /**
434             * 画面出力用のフォーマットを作æ?しますã?
435             *
436             * @param       rowNo   ãƒ??タ読み取り件数
437             * @param       updCnt  更新件数
438             * @param       data ラインモãƒ?ƒ«
439             */
440            private void printKey( final int rowNo , final int updCnt , final LineModel data ) {
441                    StringBuilder buf = new StringBuilder();
442    
443                    if( updCnt > 0 ) { buf.append( "UPDATE " ); }
444                    else                     { buf.append( "INSERT " ); }
445    
446                    buf.append( "row=[" ).append( rowNo ).append( "] : " );
447                    for( int i=0; i < updClmNos.length; i++ ) {
448                            if( i == 0 ) { buf.append( "key: " ); }
449                            else         { buf.append( " and " );  }
450                            buf.append( data.getName( updClmNos[i] ) );
451                            buf.append( " = " );
452                            buf.append( data.getValue( updClmNos[i] ) );
453                    }
454    
455                    println( buf.toString() );
456            }
457    
458            /**
459             * プロセスの処ç�?µ�果のレポã?ト表現を返しますã?
460             * 処ç�??ログラãƒ?��、å?力件数、å?力件数などのæƒ??ですã?
461             * こã?æ–?­—å?をそのまま、標準å?力に出すことで、結果レポã?トと出来るよã�?�ª
462             * 形式で出してくださいã€?
463             *
464             * @return   処ç�?µ�果のレポã?ãƒ?
465             */
466            public String report() {
467                    String report = "[" + getClass().getName() + "]" + CR
468                                    + TAB + "DBID         : " + dbid + CR
469                                    + TAB + "Input  Count : " + count + CR
470                                    + TAB + "Update Count : " + updCount + CR
471                                    + TAB + "Insert Count : " + insCount ;
472    
473                    return report ;
474            }
475    
476            /**
477             * こã?クラスの使用方法を返しますã?
478             *
479             * @return      こã?クラスの使用方æ³?
480             */
481            public String usage() {
482                    StringBuilder buf = new StringBuilder();
483    
484                    buf.append( "Process_DBMerge は、UPDATE と INSERT を指定し ãƒ??タベã?スを追åŠ?›´新"                    ).append( CR );
485                    buf.append( "する、ChainProcess インターフェースの実è£?‚¯ラスですã?"                                                  ).append( CR );
486                    buf.append( "上æµ?プロセスチェインのãƒ??タは上流から下流へと渡されますã?)から"                   ).append( CR );
487                    buf.append( "受け取っã�?LineModel をå?に、データベã?スの存在チェãƒ?‚¯を行いã€?                              ).append( CR );
488                    buf.append( "下流への処ç�?‚’振りå?けますã?"                                                                                                   ).append( CR );
489                    buf.append( CR );
490                    buf.append( "ãƒ??タベã?ス接続å?等ã?、ParamProcess のサブクラス(Process_DBParam)に"                    ).append( CR );
491                    buf.append( "設定された接ç¶?Connection)を使用しますã?"                                                                               ).append( CR );
492                    buf.append( CR );
493                    buf.append( "引数æ–?­—å?中に空白を含ã‚??合ã?、ダブルコーãƒ??ション(\"\") で括って下さã�??" ).append( CR );
494                    buf.append( "引数æ–?­—å?の ã€?』ã?前後には、空白は挟めません。å¿?�šã€?key=value の様に"             ).append( CR );
495                    buf.append( "繋げてくださいã€?                                                                                                                              ).append( CR );
496                    buf.append( CR );
497                    buf.append( "SQLæ–?�«は、{@DATE.YMDH}等ã?シスãƒ?ƒ 変数が使用できますã?"                                          ).append( CR );
498                    buf.append( CR ).append( CR );
499                    buf.append( getArgument().usage() ).append( CR );
500    
501                    return buf.toString();
502            }
503    
504            /**
505             * こã?クラスは、main メソãƒ?ƒ‰から実行できませんã€?
506             *
507             * @param       args    コマンド引数配å?
508             */
509            public static void main( final String[] args ) {
510                    LogWriter.log( new Process_DBMerge().usage() );
511            }
512    }