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
022 import org.opengion.fukurou.util.HybsEntry ;
023 import org.opengion.fukurou.util.Closer;
024 import org.opengion.fukurou.util.StringUtil; // 5.7.2.3 (2014/01/31)
025 import org.opengion.fukurou.db.ConnectionFactory;
026
027 import java.util.Map ;
028 import java.util.LinkedHashMap ;
029 import java.util.Locale ;
030
031 import java.sql.Connection;
032 import java.sql.Statement;
033 import java.sql.ResultSet;
034 import java.sql.ResultSetMetaData;
035 import java.sql.SQLException;
036
037 /**
038 * Process_DBReaderは、データベã?スから読み取ったå?容をã?LineModel に設定後ã?
039 * 下流に渡すã?FirstProcess インターフェースの実è£?‚¯ラスですã?
040 *
041 * ãƒ??タベã?スから読み取ったå?容より、LineModelを作æ?しã?下æµ?プロセス
042 * チェインは、チェインしてã�?‚‹ため、データは上流から下流へと渡されますã?)
043 * に渡しますã?ここでæŒ?®šできるのは、検索系SQL のみですã?
044 *
045 * ãƒ??タベã?ス接続å?等ã?、ParamProcess のサブクラス(Process_DBParam)に
046 * 設定された接ç¶?Connection)を使用しますã?
047 *
048 * 引数æ–?—å?中にスペã?スを含ã‚??合ã?、ダブルコーãƒ??ション("") で括って下さã�??
049 * 引数æ–?—å?の ã€?』ã?前後には、スペã?スは挟めません。å¿?�šã€?key=value の様に
050 * 繋げてくださいã€?
051 *
052 * SQLæ–?�«は、{@DATE.YMDH}等ã?シスãƒ?ƒ 変数が使用できますã?
053 *
054 * @og.formSample
055 * Process_DBReader -dbid=DBGE -sql="select * from GEA08"
056 *
057 * [ -dbid=DB接続ID ] ??dbid=DBGE (ä¾? Process_DBParam の -configFile でæŒ?®šすã‚?DBConfig.xml ファイルで規å®?
058 * [ -sql=検索SQLæ–? ] ??sql="select * from GEA08"
059 * [ -sqlFile=検索SQL?Œァ?²??] ??sqlFile=select.sql
060 * -sql= を指定しなã�??合ã?、ファイルでå¿?�šæŒ?®šしてくださいã€?
061 * [ -sql_XXXX=固定å? ] ??sql_SYSTEM_ID=GE
062 * SQLæ–?¸の{@XXXX}æ–?—å?を指定ã?固定å?で置き換えますã?
063 * WHERE SYSTEM_ID='{@SYSTEM_ID}' �WHERE SYSTEM_ID='GE'
064 * [ -asClms=置換カ?—ム名 ] ??asClms="FGJ:CDJ SEQ123:UNIQ" å…?½¶?—ム名:新?¶?—ム名 の?½?�゚ー?½区åˆ?‚Š
065 * [ -fetchSize=100 ] ?šフェãƒ?ƒ�する行数(初期値:100)
066 * [ -display=[false/true]] ?š結果を標準å?力に表示する(true)かしなã�?false)ã�?初期値:false[表示しない])
067 * [ -debug=[false/true] ] ?šデバッグæƒ??を標準å?力に表示する(true)かしなã�?false)ã�?初期値:false[表示しない])
068 *
069 * @version 4.0
070 * @author Kazuhiko Hasegawa
071 * @since JDK5.0,
072 */
073 public class Process_DBReader extends AbstractProcess implements FirstProcess {
074 private static final String SQL_KEY = "sql_" ;
075
076 private Connection connection = null;
077 private Statement stmt = null ;
078 private ResultSet resultSet = null;
079 private LineModel newData = null;
080 private int count = 0;
081 private int fetchSize = 100;
082
083 private String dbid = null;
084 private boolean display = false; // 表示しなã�?
085 private boolean debug = false; // 5.7.3.0 (2014/02/07) ãƒ?ƒ�ãƒ?‚°æƒ??
086
087 private static final Map<String,String> mustProparty ; // ?»プロパティ?½å¿??チェãƒ?‚¯用 Map
088 private static final Map<String,String> usableProparty ; // ?»プロパティ?½整合æ?チェãƒ?‚¯ Map
089
090 static {
091 mustProparty = new LinkedHashMap<String,String>();
092
093 usableProparty = new LinkedHashMap<String,String>();
094 usableProparty.put( "dbid", "Process_DBParam の -configFile でæŒ?®šすã‚?DBConfig.xml ファイルで規å®? );
095 usableProparty.put( "sql", "検索SQLæ–?sql or sqlFile å¿??)ä¾? \"select * from GEA08\"" );
096 usableProparty.put( "sqlFile", "検索SQLファイル(sql or sqlFile å¿??)ä¾? select.sql" );
097 usableProparty.put( "sql_", "SQLæ–?¸の{@XXXX}æ–?—å?を指定ã?固定å?で置き換えますã?" +
098 CR + "WHERE SYSTEM_ID='{@SYSTEM_ID}' �WHERE SYSTEM_ID='GE'" );
099 // 5.7.2.3 (2014/01/31) asClms 追åŠ?
100 usableProparty.put( "asClms", "å…?½¶?—ム名:新?¶?—ム名 の?½?�゚ー?½区åˆ?‚Šで?¶?—ム名の置換を行う" );
101 usableProparty.put( "fetchSize","フェãƒ?ƒ�する行数 (初期値:100)" );
102 usableProparty.put( "display", "結果を標準å?力に表示する(true)かしなã�?false)ã�? +
103 CR + "(初期値:false:表示しなã�?" );
104 usableProparty.put( "debug", "ãƒ?ƒ�ãƒ?‚°æƒ??を標準å?力に表示する(true)かしなã�?false)ã�? +
105 CR + "(初期値:false:表示しなã�?" ); // 5.7.3.0 (2014/02/07) ãƒ?ƒ�ãƒ?‚°æƒ??
106 }
107
108 /**
109 * ãƒ?ƒ•ォルトコンストラクターã€?
110 * こã?クラスは、動çš?½œæ?されますã?ãƒ?ƒ•ォルトコンストラクターでã€?
111 * super クラスに対して、å¿?¦�な初期化を行っておきますã?
112 *
113 */
114 public Process_DBReader() {
115 super( "org.opengion.fukurou.process.Process_DBReader",mustProparty,usableProparty );
116 }
117
118 /**
119 * プロセスの初期化を行いますã?初めにä¸?º¦ã�?�‘、呼び出されますã?
120 * 初期処ç�?ファイルオープンã€?¼¤?¢オープンç?に使用しますã?
121 *
122 * @og.rev 5.7.2.2 (2014/01/24) SQL実行エラーを少し詳細に出力しますã?
123 * @og.rev 5.7.2.3 (2014/01/31) asClms 追åŠ?
124 *
125 * @param paramProcess ãƒ??タベã?スの接続å?æƒ??などを持ってã�?‚‹オブジェクãƒ?
126 */
127 public void init( final ParamProcess paramProcess ) {
128 Argument arg = getArgument();
129
130 String sql = arg.getFileProparty("sql","sqlFile",true);
131
132 // 5.7.2.3 (2014/01/31) asClms 追åŠ?
133 String asClms = arg.getProparty("asClms");
134
135 String fSize = arg.getProparty("fetchSize");
136 display = arg.getProparty("display",display);
137 debug = arg.getProparty("debug",debug); // 5.7.3.0 (2014/02/07) ãƒ?ƒ�ãƒ?‚°æƒ??
138 // if( debug ) { println( arg.toString() ); } // 5.7.3.0 (2014/02/07) ãƒ?ƒ�ãƒ?‚°æƒ??
139
140 dbid = arg.getProparty("dbid");
141 connection = paramProcess.getConnection( dbid );
142
143 // 3.8.0.1 (2005/06/17) SQLæ–?? {@XXXX} æ–?—å?の固定å?への置き換ã�?
144 HybsEntry[] entry =arg.getEntrys(SQL_KEY); //配å?
145 SystemParameter sysParam = new SystemParameter( sql );
146 sql = sysParam.replace( entry );
147
148 // SQLæ–?? {@XXXX} æ–?—å?の固定å?への置き換ã�?
149 if( fSize != null ) { fetchSize = Integer.parseInt( fSize ); }
150
151 try {
152 stmt = connection.createStatement();
153 if( fetchSize > 0 ) { stmt.setFetchSize( fetchSize ); }
154 resultSet = stmt.executeQuery( sql );
155
156 // 5.7.2.3 (2014/01/31) asClms 処ç�?‚’追åŠ??
157 // newData = createLineModel( resultSet );
158 newData = createLineModel( resultSet,asClms );
159
160 if( display ) { println( newData.nameLine() ); }
161 }
162 catch (SQLException ex) {
163 // 5.7.2.2 (2014/01/24) SQL実行エラーを少し詳細に出力しますã?
164 String errMsg = "Query の実行に問題がありますã?" + CR
165 + "errMsg=[" + ex.getMessage() + "]" + CR
166 + "errCode=[" + ex.getErrorCode() + "] State=[" + ex.getSQLState() + "]" + CR
167 + "dbid=[" + dbid + "]" + CR
168 + "sql =[" + sql + "]" ;
169 // String errMsg = "Query の実行に問題がありますã?[" + sql + "]" ;
170 throw new RuntimeException( errMsg,ex );
171 }
172 }
173
174 /**
175 * プロセスの終äº?‚’行いますã?æœ?¾Œにä¸?º¦ã�?�‘、呼び出されますã?
176 * 終äº??ç�?ファイルクローズã€?¼¤?¢クローズç?に使用しますã?
177 *
178 * @og.rev 4.0.0.0 (2007/11/27) commit,rollback,remove 処ç�?‚’追åŠ?
179 *
180 * @param isOK トã?タルで、OKã�?�£たかどã�?�‹[true:成功/false:失敗]
181 */
182 public void end( final boolean isOK ) {
183 boolean flag1 = Closer.resultClose( resultSet );
184 resultSet = null;
185 boolean flag2 = Closer.stmtClose( stmt );
186 stmt = null;
187
188 ConnectionFactory.remove( connection,dbid );
189
190 if( !flag1 || !flag2 ) {
191 String errMsg = "スãƒ??トメントをクローズ出来ませんã€?;
192 throw new RuntimeException( errMsg );
193 }
194 }
195
196 /**
197 * こã?ãƒ??タの処ç�?�«おいて、次の処ç�?�Œ出来るかどã�?�‹を問ã�?�ˆわせますã?
198 * こã?呼び出し1回毎に、次のãƒ??タを取得する準備を行いますã?
199 *
200 * @og.rev 5.7.2.2 (2014/01/24) SQL実行エラーを少し詳細に出力しますã?
201 *
202 * @return 処ç�?�§きる:true / 処ç�?�§きなã�?false
203 */
204 public boolean next() {
205 try {
206 return resultSet.next() ;
207 }
208 catch (SQLException ex) {
209 String errMsg = "ネクストすることがå?来ませんã€?
210 + "errMsg=[" + ex.getMessage() + "]" + CR
211 + "errCode=[" + ex.getErrorCode() + "] State=[" + ex.getSQLState() + "]" + CR ;
212 // String errMsg = "ネクストすることがå?来ませんã€?;
213 throw new RuntimeException( errMsg,ex );
214 }
215 }
216
217 /**
218 * æœ??にã€?行データである LineModel を作æ?しまã�?
219 * FirstProcess は、次ã€?�¨処ç�?‚’チェインしてã�?��æœ??の行データã‚?
220 * 作æ?して、後続ã? ChainProcess クラスに処ç�?ƒ‡ータを渡しますã?
221 *
222 * @og.rev 5.7.2.2 (2014/01/24) SQL実行エラーを少し詳細に出力しますã?
223 *
224 * @param rowNo 処ç�?¸の行番号
225 *
226 * @return 処ç�?¤‰換後ã?LineModel
227 */
228 public LineModel makeLineModel( final int rowNo ) {
229 count++ ;
230 try {
231 for(int clm = 0; clm < newData.size(); clm++) {
232 Object obj = resultSet.getObject(clm+1);
233 if( obj == null ) {
234 // newData.setValue( clm, "" );
235 newData.setValue( clm, null );
236 }
237 else {
238 newData.setValue( clm, obj );
239 }
240 }
241 newData.setRowNo( rowNo );
242 if( display ) { println( newData.dataLine() ); }
243 }
244 catch (SQLException ex) {
245 // 5.7.2.2 (2014/01/24) SQL実行エラーを少し詳細に出力しますã?
246 String errMsg = "ãƒ??タをå?ç�?�§きませんでしたã€?" + rowNo + "]件目 " + CR
247 + "errMsg=[" + ex.getMessage() + "]" + CR
248 + "errCode=[" + ex.getErrorCode() + "] State=[" + ex.getSQLState() + "]" + CR
249 + "dbid=[" + dbid + "]" + CR
250 + "data=[" + newData.dataLine() + "]" + CR ;
251 // String errMsg = "ãƒ??タをå?ç�?�§きませんでしたã€?" + rowNo + "]件目 "
252 // + newData.toString() ;
253 throw new RuntimeException( errMsg,ex );
254 }
255 return newData;
256 }
257
258 /**
259 * å†?ƒ¨で使用する LineModel を作æ?しますã?
260 * こã?クラスは、ã?ロセスチェインの基点となりますã?で、新è¦?LineModel を返しますã?
261 * Exception 以外では、å¿?�š LineModel オブジェクトを返しますã?
262 * 第?’引数は、カラãƒ?��の置き換え指示ですã?null の場合ã?、何もしませんã€?
263 * 通常は、SELECT CLM1 AS CLM2 FROM *** とするç®?‰€をã?CLM1:CLM2 とæŒ?®šする事で
264 * SELECT CLM1 FROM *** のまま、以降ã?処ç�?‚’ CLM2 で扱えますã?
265 *
266 * @og.rev 5.7.2.2 (2014/01/24) SQL実行エラーを少し詳細に出力しますã?
267 * @og.rev 5.7.2.3 (2014/01/31) asClms 追åŠ?
268 *
269 * @param rs ãƒ??タベã?スカーソル(リザルトセãƒ?ƒˆ)
270 * @param asClms å…?½¶?—ム名:新?¶?—ム名 の?½?�゚ー?½区åˆ?‚Šæ–?—å?
271 *
272 * @return ãƒ??タベã?スから取り出して変換した LineModel
273 * @throws RuntimeException カラãƒ?��を取得できなかったå?合ã?
274 */
275 // private LineModel createLineModel( final ResultSet rs ) {
276 private LineModel createLineModel( final ResultSet rs , final String asClms ) {
277 LineModel model = new LineModel();
278
279 try {
280 ResultSetMetaData metaData = rs.getMetaData();
281
282 int size = metaData.getColumnCount();
283 model.init( size );
284
285 for(int clm = 0; clm < size; clm++) {
286 String name = (metaData.getColumnLabel(clm+1)).toUpperCase(Locale.JAPAN) ;
287 // 5.7.2.3 (2014/01/31) asClms 追åŠ?
288 if( asClms != null ) {
289 // asClms の null判定も、toUpperCase 処ç�?‚‚行ってã�?‚‹がã?判りにくいのでã€?
290 name = StringUtil.caseReplace( name,asClms,false );
291 }
292 model.setName( clm,name );
293 }
294 }
295 catch (SQLException ex) {
296 // 5.7.2.2 (2014/01/24) SQL実行エラーを少し詳細に出力しますã?
297 String errMsg = "ResultSetMetaData から、カラãƒ?��を取得できませんでしたã€? + CR
298 + "errMsg=[" + ex.getMessage() + "]" + CR
299 + "errCode=[" + ex.getErrorCode() + "] State=[" + ex.getSQLState() + "]" + CR
300 + "dbid=[" + dbid + "]" + CR ;
301 // String errMsg = "ResultSetMetaData から、カラãƒ?��を取得できませんでしたã€?;
302 throw new RuntimeException( errMsg,ex );
303 }
304 return model;
305 }
306
307 /**
308 * プロセスの処ç�?µ�果のレポã?ト表現を返しますã?
309 * 処ç�??ログラãƒ?��、å?力件数、å?力件数などのæƒ??ですã?
310 * こã?æ–?—å?をそのまま、標準å?力に出すことで、結果レポã?トと出来るよã�?�ª
311 * 形式で出してくださいã€?
312 *
313 * @return 処ç�?µ�果のレポã?ãƒ?
314 */
315 public String report() {
316 String report = "[" + getClass().getName() + "]" + CR
317 + TAB + "DBID : " + dbid + CR
318 + TAB + "Input Count : " + count ;
319
320 return report ;
321 }
322
323 /**
324 * こã?クラスの使用方法を返しますã?
325 *
326 * @return こã?クラスの使用方æ³?
327 */
328 public String usage() {
329 StringBuilder buf = new StringBuilder();
330
331 buf.append( "Process_DBReaderは、データベã?スから読み取ったå?容をã?LineModel に設定後ã?" ).append( CR );
332 buf.append( "下流に渡すã?FirstProcess インターフェースの実è£?‚¯ラスですã?" ).append( CR );
333 buf.append( CR );
334 buf.append( "ãƒ??タベã?スから読み取ったå?容より、LineModelを作æ?しã?下æµ?プロセス" ).append( CR );
335 buf.append( "チェインは、チェインしてã�?‚‹ため、データは上流から下流へと渡されますã?)" ).append( CR );
336 buf.append( "に渡しますã?ここでæŒ?®šできるのは、検索系SQL のみですã?" ).append( CR );
337 buf.append( CR );
338 buf.append( "ãƒ??タベã?ス接続å?等ã?、ParamProcess のサブクラス(Process_DBParam)に" ).append( CR );
339 buf.append( "設定された接ç¶?Connection)を使用しますã?" ).append( CR );
340 buf.append( CR );
341 buf.append( "引数æ–?—å?中に空白を含ã‚??合ã?、ダブルコーãƒ??ション(\"\") で括って下さã�??" ).append( CR );
342 buf.append( "引数æ–?—å?の ã€?』ã?前後には、空白は挟めません。å¿?�šã€?key=value の様に" ).append( CR );
343 buf.append( "繋げてくださいã€? ).append( CR );
344 buf.append( CR );
345 buf.append( "SQLæ–?�«は、{@DATE.YMDH}等ã?シスãƒ?ƒ 変数が使用できますã?" ).append( CR );
346 buf.append( CR ).append( CR );
347
348 buf.append( getArgument().usage() ).append( CR );
349
350 return buf.toString();
351 }
352
353 /**
354 * こã?クラスは、main メソãƒ?ƒ‰から実行できませんã€?
355 *
356 * @param args コマンド引数配å?
357 */
358 public static void main( final String[] args ) {
359 LogWriter.log( new Process_DBReader().usage() );
360 }
361 }