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