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