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 }