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 */ 016package org.opengion.fukurou.db; 017 018import org.opengion.fukurou.util.AbstractObjectPool; 019import org.opengion.fukurou.system.Closer; 020import org.opengion.fukurou.system.OgRuntimeException ; // 6.4.2.0 (2016/01/29) 021import static org.opengion.fukurou.system.HybsConst.CR; // 6.1.0.0 (2014/12/26) refactoring 022import static org.opengion.fukurou.system.HybsConst.BUFFER_MIDDLE; // 6.4.3.3 (2016/03/04) 023 024 // import java.util.concurrent.ExecutorService; // 7.1.0.0 (2020/01/20) 025 // import java.util.concurrent.Executors; // 7.1.0.0 (2020/01/20) 026 // import java.util.concurrent.Future; // 7.1.0.0 (2020/01/20) 027 // import java.util.concurrent.Callable; // 7.1.0.0 (2020/01/20) 028 // import java.util.concurrent.TimeUnit; // 7.1.0.0 (2020/01/20) 029 // import java.util.concurrent.ExecutionException; // 7.1.0.0 (2020/01/20) 030 // import java.util.concurrent.TimeoutException; // 7.1.0.0 (2020/01/20) 031 // import java.util.concurrent.CancellationException; // 7.1.0.0 (2020/01/20) 032import java.util.concurrent.ConcurrentMap; // 6.4.3.3 (2016/03/04) 033import java.util.concurrent.ConcurrentHashMap; 034import java.util.Locale; 035import java.util.Properties; 036import java.sql.Connection; 037import java.sql.SQLException; 038import java.sql.DriverManager; 039import java.sql.DatabaseMetaData; 040 041/** 042 * データベースのコネクションオブジェクトを取得する為に使用するファクトリクラスです。 043 * 044 * Connection.connection() メソッドで、Connectionオブジェクトを取得します。 045 * Connection#close() メソッドで、内部的に ConnectionFactory にオブジェクトを戻す 046 * 事によって、Connectionオブジェクトのプーリングを行なっています。 047 * 048 * コネクションオブジェクトは、プールから貸し出します。 049 * つまり、貸し出し中には、プールには、オブジェクトは残っていません。 050 * その状態で、コネクションオブジェクトをclose()しない場合は、オブジェクトが破棄されて、 051 * 貸し出し中カウントと実際のオブジェクト数が食い違い、リソースが不足します。 052 * 必ず、作成したオブジェクトは、close()メソッドを呼び出して、プールに返して下さい。 053 * 054 * システムリソースの USE_DB_APPLICATION_INFO=true の場合、コネクションにアプリケーション 055 * 情報を追記するため、ApplicationInfoオブジェクトを使用します。 056 * このオブジェクトは、jsp/common/session-init.jsp にてユーザー情報とアプリケーション 057 * 情報を画面アクセスごとに設定します。 058 * 059 * @og.group DB/Shell制御 060 * @og.rev 4.0.0.0 (2007/10/16) パッケージ移動(hayabusa/db ⇒ fukurou/db) 061 * 062 * @version 4.0 063 * @author Kazuhiko Hasegawa 064 * @since JDK5.0, 065 */ 066public final class ConnectionFactory { 067 /** 6.4.3.4 (2016/03/11) PMD refactoring. HashMap → ConcurrentHashMap に置き換え。 */ 068 private static final ConcurrentMap<String,ConnectionPool> CONN_MAP = new ConcurrentHashMap<>(); 069 070 // 4.0.0.0 (2007/10/10) キャッシュされた、初期ConnectionPool を使用 071 // 4.0.0.0 (2007/10/29) 初期値をここでセットする 072 private static String defDBID = "DEFAULT"; // 6.3.9.1 (2015/11/27) Variables should start with a lowercase character(PMD) 073 private static ConnectionPool defPOOL ; // 6.3.9.1 (2015/11/27) Variables should start with a lowercase character(PMD) 074 private static DatabaseConfig dbConf ; 075 076 /** 077 * デフォルトコンストラクターをprivateにして、 078 * オブジェクトの生成をさせないようにする。 079 * 080 */ 081 private ConnectionFactory() { 082 // オブジェクトの生成をさせないようにする。 083 } 084 085 /** 086 * 初期化メソッドです。 087 * <pre> 088 * 1)第二引数にXMLファイルをクラスローダ基底からの相対パスで指定した場合は 089 * そのXMLを利用してDBConfigオブジェクトを作成します。例:ConnectionFactory.init( CONTEXT_NAME, "../DBConfig.xml") 090 * nullの場合はWEB-INF/DBConfig.xmlを利用します。例:ConnectionFactory.init( CONTEXT_NAME, null) 091 * 2)キャッシュ初期ConnectionPoolのキーを設定してキャッシュプールを作ります。 092 * この値がnullの場合は"DEFAULT"が設定されます。 093 * </pre> 094 * 095 * <strong>このクラスを利用する場合は必ず最初にこのメソッドを実行する必要があります。</strong> 096 * キャッシュとDBConfigオブジェクトの同期化はされていないので初期化以外での利用は避けて下さい。 097 * 098 * @og.rev 4.0.0.0 (2007/11/05) 新規作成 099 * @og.rev 6.4.3.3 (2016/03/04) DatabaseConfig のコンストラクター修正で、引数の nullチェックは不要。 100 * @og.rev 7.1.0.0 (2020/01/20) #ConnectionPool(DatabaseConfig,String) に統一 101 * 102 * @param defPoolKey 初期DBID名(nullの場合は、"DEFAULT") 103 * @param xmlFileName DBConfig.xmlファイルのファイル名(nullの場合は、WEB-INF/DBConfig.xml) 104 */ 105 public static void init( final String defPoolKey, final String xmlFileName ) { 106 // DBConfigオブジェクトの作成 107 // 6.4.3.3 (2016/03/04) DatabaseConfig のコンストラクター修正で、引数の nullチェックは不要。 108 dbConf = new DatabaseConfig( xmlFileName ); 109 110 if( defPoolKey == null || defPoolKey.isEmpty() || dbConf.getDbid( defPoolKey ) == null ) { 111 defDBID = "DEFAULT"; 112 } 113 else { 114 defDBID = defPoolKey; 115 } 116 117 defPOOL = new ConnectionPool( dbConf,defDBID ); // 7.1.0.0 (2020/01/20) 118// 119// final EDbid edbid = dbConf.getDbid( defDBID ); 120// if( edbid == null ) { 121// final String errMsg = "初期化時に、指定のDBIDキーが存在しません。" 122// + "[Key =" 123// + defDBID 124// + "]"; 125// throw new OgRuntimeException( errMsg ); 126// } 127// 128// // if( DEF_POOL != null ) { DEF_POOL.clear(); } // 6.0.2.5 (2014/10/31) nullでなければ初期化する。 129// defPOOL = new ConnectionPool( edbid ); 130 } 131 132 /** 133 * コネクションオブジェクトを取得します。 134 * 遅い初期化を行なう事により、実際に必要となるまでコネクションオブジェクトは 135 * 作成しません。 136 * 最大プール数に達して、なおかつ、すべてのConnectionが貸し出し中の場合 137 * 138 * @og.rev 2.1.1.3 (2002/11/22) コネクションID が null の場合に DEFAULT から所得するように変更。 139 * @og.rev 3.1.0.0 (2003/03/20) Hashtable を使用している箇所で、非同期でも構わない箇所を、HashMap に置換え。 140 * @og.rev 3.5.6.2 (2004/07/05) 文字列の連結にStringBuilderを使用します。 141 * @og.rev 3.8.7.0 (2006/12/15) アクセスログ取得の為、ApplicationInfoオブジェクトを設定 142 * @og.rev 3.8.8.2 (2007/01/26) USE_DB_APPLICATION_INFO ⇒ pool.useApplicationInfo() 変更 143 * @og.rev 4.0.0.0 (2007/10/10) キャッシュされた、初期ConnectionPool を使用 144 * @og.rev 4.1.0.1 (2008/01/21) 登録時に、大文字に変換する。 145 * @og.rev 6.4.3.3 (2016/03/04) Map#computeIfAbsent で対応する。 146 * 147 * @param dbid 接続先ID 148 * @param appInfo アプリ情報オブジェクト 149 * 150 * @return コネクションオブジェクト 151 */ 152 public static Connection connection( final String dbid , final ApplicationInfo appInfo ) { 153 final ConnectionPool pool ; 154 if( dbid == null || dbid.isEmpty() || defDBID.equalsIgnoreCase( dbid ) ) { 155 pool = defPOOL ; 156 } 157 else { 158 final String udbid = dbid.toUpperCase( Locale.JAPAN ); // 大文字化 159 160 // 6.4.3.3 (2016/03/04) Map#computeIfAbsent で対応する。 161 // Map#computeIfAbsent : 戻り値は、既存の、または計算された値。追加有り、置換なし、削除なし 162 // ※ 注意:ConnectionPool のコンストラクタに、従来と異なり、DatabaseConfig オブジェクトを渡しています。 163 pool = CONN_MAP.computeIfAbsent( udbid , k -> new ConnectionPool( dbConf,udbid ) ); 164 } 165 166 final Connection conn = pool.newInstance(); 167 168 // 3.8.7.0 (2006/12/15) アクセスログ取得の為、ApplicationInfoオブジェクトを使用 169 // 3.8.8.2 (2007/01/26) ORACLE 以外は、使用しません。 170 // 4.0.0.0 (2007/11/29) 入れ子if の統合 171 if( appInfo != null && pool.useApplicationInfo() ) { 172 appInfo.callAppInfo( conn ); 173 } 174 return conn; 175 } 176 177 /** 178 * コネクションオブジェクトをプールに戻します。 179 * Connectionオブジェクトは、close()メソッドで、自分自身を ConnectionFactory の 180 * プールに戻します。 181 * それ以外のコネクションオブジェクトをプールに戻す場合は、このメソッドを使用します。 182 * 183 * @og.rev 2.1.1.3 (2002/11/22) コネクションID が null の場合に DEFAULT から所得するように変更。 184 * @og.rev 4.0.0.0 (2007/10/10) キャッシュされた、初期ConnectionPool を使用 185 * @og.rev 4.1.0.1 (2008/01/21) 登録時に、大文字に変換する。 186 * @og.rev 5.9.32.0 (2018/05/18) プールに戻す前に明示的にcommitをかける 187 * 188 * @param conn コネクションオブジェクト 189 * @param dbid 接続先ID 190 */ 191 public static void close( final Connection conn,final String dbid ) { 192 if( conn != null ) { 193 Closer.commit( conn ); // 5.9.32.0 (2018/05/18) プールに戻す前に明示的にcommitをかける 194 if( dbid == null || dbid.isEmpty() || defDBID.equalsIgnoreCase( dbid ) ) { 195 defPOOL.release( conn ) ; 196 } 197 else { 198 final String udbid = dbid.toUpperCase( Locale.JAPAN ); // 大文字化 199 // synchronized( CONN_MAP ) { 200 final ConnectionPool pool = CONN_MAP.get( udbid ); 201 if( pool != null ) { 202 pool.release( conn ); 203 } 204 // } 205 } 206 } 207 } 208 209 /** 210 * コネクションオブジェクトを物理的に削除(クローズ)戻します。 211 * これは、コネクション等がエラーを起こした場合に、プールに戻すのではなく、 212 * 接続を閉じる場合に、使用されます。 213 * 214 * @og.rev 2.1.1.3 (2002/11/22) コネクションID が null の場合に DEFAULT から所得するように変更。 215 * @og.rev 4.0.0.0 (2007/10/10) キャッシュされた、初期ConnectionPool を使用 216 * @og.rev 4.1.0.1 (2008/01/21) 登録時に、大文字に変換する。 217 * 218 * @param conn コネクションオブジェクト 219 * @param dbid 接続先ID 220 */ 221 public static void remove( final Connection conn,final String dbid ) { 222 if( conn != null ) { 223 if( dbid == null || dbid.isEmpty() || defDBID.equalsIgnoreCase( dbid ) ) { 224 defPOOL.remove( conn ) ; 225 } 226 else { 227 final String udbid = dbid.toUpperCase( Locale.JAPAN ); // 大文字化 228 // synchronized( CONN_MAP ) { 229 final ConnectionPool pool = CONN_MAP.get( udbid ); 230 if( pool != null ) { 231 pool.remove( conn ); 232 } 233 // } 234 } 235 } 236 } 237 238 /** 239 * コネクションオブジェクトを実際にすべてクローズします。 240 * コネクションプールの再編成や、管理者による強制クローズに使用します。 241 * 242 * クローズに失敗(コネクションが貸し出し中)の場合は、内部的に 243 * DB_CLOSE_RETRY_TIME だけ待機して、DB_CLOSE_RETRY_COUNT 回数だけ試行します。 244 * それでもクローズできない場合は、RuntimeException を throw します。 245 * 246 * @og.rev 4.0.0.0 (2005/01/31) ロジック見直し。 pool.clear() で、基本的にはすべて削除されます。 247 * @og.rev 4.0.0.0 (2007/10/10) キャッシュされた、初期ConnectionPool を使用 248 * @og.rev 6.4.3.3 (2016/03/04) Map#forEach で対応する。 249 */ 250 public static void realClose() { 251 synchronized( defPOOL ) { 252 if( ! defPOOL.isEmpty() ) { 253 defPOOL.clear(); 254 } 255 } 256 257 // 6.4.3.3 (2016/03/04) Map#forEach で対応する。 258 CONN_MAP.forEach( (id,pl) -> pl.clear() ); 259 CONN_MAP.clear(); 260 } 261 262 /** 263 * ConnectionFactory の現在の状況(詳細メッセージ)を返します。 264 * これは、コネクションプールの数(最大値,作成済み数など)を確認する為のものです。 265 * 266 * @og.rev 4.0.0.0 (2007/10/10) キャッシュされた、初期ConnectionPool を使用 267 * 268 * @return 現在の状態表示 269 * @og.rtnNotNull 270 */ 271 public static String information() { 272 return information( true ); 273 } 274 275 /** 276 * ConnectionFactory の現在の状況を返します。 277 * これは、コネクションプールの数(最大値,作成済み数など)を確認する為のものです。 278 * 引数により詳細メッセージかどうかを指定できます。 279 * 280 * @og.rev 4.0.0.0 (2007/10/10) キャッシュされた、初期ConnectionPool を使用 281 * @og.rev 5.3.4.0 (2011/04/01) 詳細メッセージ用引数を追加 282 * @og.rev 5.6.7.3 (2013/08/23) 若干の修正 283 * @og.rev 6.4.3.3 (2016/03/04) Map#forEach で対応する。 284 * @og.rev 7.0.1.0 (2018/10/15) XHTML → HTML5 対応(空要素の、"/>" 止めを、">" に変更します)。 285 * @og.rev 7.1.0.0 (2020/01/20) DB未接続のDBIDは表示から除外します。 286 * 287 * @param isDetail 詳細メッセージかどうか [true:詳細メッセージ/false:簡易メッセージ] 288 * 289 * @return 現在の状態表示 290 * @og.rtnNotNull 291 */ 292 public static String information(final boolean isDetail ) { 293 // 4.0.0.0 (2007/10/25) hybsとの依存関係を弱めるため。 294 final StringBuilder strBuf = new StringBuilder( BUFFER_MIDDLE ); 295 296 strBuf.append( "<b>【Connection Information】</b>" ).append( CR ); // 5.6.7.3 (2013/08/23) 若干の修正 297 298 synchronized( defPOOL ) { 299 if( ! defPOOL.isEmpty() ) { 300 // 5.3.4.0 (2011/04/01) 詳細メッセージ用引数を追加 301 if( isDetail ) { 302// strBuf.append( defPOOL.toString() ).append( "<br /><hr />" ); 303 strBuf.append( defPOOL.toString() ).append( "<br><hr>" ); // 7.0.1.0 (2018/10/15) 304 } 305 else { 306 strBuf.append( defPOOL.dbidInfo() ); 307 } 308 } 309 } 310 311 // 6.4.3.3 (2016/03/04) Map#forEach で対応する。 312 CONN_MAP.forEach( (id,pl) -> { 313 if( pl.getDBName() != null ) { // 7.1.0.0 (2020/01/20) DB未接続のDBIDは表示から除外 314 if( isDetail ) { 315// strBuf.append( pl.toString() ).append( "<br /><hr />" ); 316 strBuf.append( pl.toString() ).append( "<br><hr>" ); // 7.0.1.0 (2018/10/15) 317 } 318 else { 319 strBuf.append( pl.dbidInfo() ); 320 } 321 } 322 } ); 323 324 return strBuf.append( CR ).toString(); 325 } 326 327 /** 328 * この接続が、PreparedStatement#getParameterMetaData() を使用するかどうかを判定します。 329 * 330 * PreparedStatement に対して、String化された 数字などを setObject( int,String ) するとき、 331 * ORACLE と SQLServer は、そのまま設定すれば、自動的に変換されます。 332 * postgreSQL では、ParameterMetaData#getParameterType(int) で、カラムタイプを取得し、 333 * setObject( int,String,int ) する必要があります。 334 * その判定に、このメソッドを使用します。 335 * この結果は、あくまで、各種データベース毎の実地調査の結果を元に、判定結果を 336 * 返すようにしています。 337 * ORACLE の場合は、使用しない(false)が返るように設定しています。 338 * SQLServer では、ORACLEと同様に、false を返します。 339 * 340 * このメソッドは、元々、ApplicationInfo#useParameterMetaData(Connection) に有ったものを 341 * EDbid から取得するように修正したものです。 342 * 343 * @og.rev 5.3.8.0 (2011/08/01) 新規追加 344 * @og.rev 6.4.3.3 (2016/03/04) EDbid のnullチェックを追加 345 * 346 * @param dbid 接続先ID 347 * 348 * @return [true:使用する/false:その他] 349 */ 350 public static boolean useParameterMetaData( final String dbid ) { 351 352 // 6.1.0.0 (2014/12/26) refactoring の一環 353 final String udbid = dbid == null || dbid.isEmpty() ? defDBID : dbid.toUpperCase( Locale.JAPAN ) ; // 6.4.2.1 (2016/02/05) PMD refactoring. Useless parentheses. 354 355 final EDbid edbid = dbConf.getDbid( udbid ); 356 357 return edbid != null && edbid.useParamMetaData(); 358 } 359 360 /** 361 * 接続先のDB名に対応した、enum (DBName) を返します(toUpperCase)。 362 * 363 * @og.rev 5.1.4.0 (2010/03/01) getDBFullName の代わりに新規作成 364 * @og.rev 5.7.7.2 (2014/06/20) 最初の取得時のエラー回避 365 * 366 * @param dbid 接続先ID 367 * 368 * @return 接続先のDB名 369 * @og.rtnNotNull 370 */ 371 public static String getDBName( final String dbid ) { 372 final String dbName; 373 374 if( dbid == null || dbid.isEmpty() || defDBID.equalsIgnoreCase( dbid ) ) { 375 dbName = defPOOL.getDBName(); 376 } 377 else { 378 final String udbid = dbid.toUpperCase( Locale.JAPAN ); // 大文字化 379 ConnectionPool pool = null; 380 // synchronized( CONN_MAP ) { 381 pool = CONN_MAP.get( udbid ); 382 if( pool == null ) { 383 connection( dbid, null ); // ダミーで、コネクトする。 384 pool = CONN_MAP.get( udbid ); // connectionで、CONN_MAP に設定しているため、もう一度、取得する。 385 } 386 // } 387 // 6.4.1.1 (2016/01/16) PMD refactoring. Avoid if (x != y) ..; else ..; 388 if( pool == null ) { 389 final String errMsg = "指定のDBIDキーに対応するデータベース名を取得出来ません。" 390 + "[Key =" + dbid + "]"; 391 throw new OgRuntimeException( errMsg ); 392 } 393 394 dbName = pool.getDBName(); 395 } 396 397 return dbName.toUpperCase( Locale.JAPAN ); 398 } 399 400 /** 401 * ConnectionPool は、AbstractObjectPool を継承した オブジェクトプールです。 402 * 403 * コネクションオブジェクトをプールすることにより、ConnectionFactory で 404 * 管理する Map オブジェクトの実態として、各ID毎の コネクションをキープします。 405 * 406 * @og.rev 7.1.0.0 (2020/01/20) Connection 作成時のタイムアウトを用意します。 407 * 408 * @og.group DB/Shell制御 409 * 410 * @version 4.0 411 * @author Kazuhiko Hasegawa 412 * @since JDK5.0, 413 */ 414 // class ConnectionPool extends AbstractObjectPool<Connection> { 415 private static final class ConnectionPool extends AbstractObjectPool<Connection> { 416 private final transient EDbid edbid; 417 private final static int TIMEOUT = 10; // 7.1.0.0 (2020/01/20) 418 419 /** 420 * DatabaseConfig と、dbid を指定して作成する コンストラクター 421 * オブジェクト作成時のMap設定で、一連の処理を行うために、エラーチェックをもつ 422 * コンストラクターを用意します。 423 * DBID が null の場合は、"DEFAULT" が使用されます。 424 * 425 * @og.rev 6.4.3.3 (2016/03/04) 処理の簡素化のための新規コンストラクター追加 426 * 427 * @param dbConf DatabaseConfigオブジェクト 428 * @param dbid 接続先ID(大文字に変換済み) 429 */ 430 private ConnectionPool( final DatabaseConfig dbConf , final String dbid ) { 431 super(); 432 433 final EDbid edbid = dbConf.getDbid( dbid ); 434 if( edbid == null ) { 435 final String errMsg = "指定のDBIDキーが存在しません。" 436 + "[Key =" 437 + dbid 438 + "]"; 439 throw new OgRuntimeException( errMsg ); 440 } 441 442 this.edbid = edbid; 443 init( edbid.getMincount(),edbid.getMaxcount(),true,edbid.getPooltime() ); 444 } 445 446// /** 447// * DBID を指定して作成する コンストラクター 448// * DBID をキーに、 HybsSystem.sys メソッドのデータベース変数を取得します。 449// * 取得するのは、 DBID + _DB_URL/_DB_USER/_DB_PASSWD/_DB_MINCOUNT/_DB_MAXCOUNT 450// * です。 451// * DBID が null の場合は、"DEFAULT" が使用されます。 452// * 453// * @og.rev 3.5.4.3 (2004/01/05) キャッシュの寿命を指定 454// * @og.rev 3.5.4.7 (2004/02/06) DBID のゼロストリングチェック追加 455// * @og.rev 4.0.0.0 (2007/10/10) キャッシュされた、初期ConnectionPool を使用 456// * @og.rev 4.0.0.0 (2007/10/25) DB設定情報のXML化に伴う変更 457// * @og.rev 6.4.1.1 (2016/01/16) PMD refactoring. It is a good practice to call super() in a constructor 458// * @og.rev 7.1.0.0 (2020/01/20) #ConnectionPool(DatabaseConfig,String) に統一 459// * 460// * @param edbid 接続先情報オブジェクト 461// */ 462// public ConnectionPool( final EDbid edbid ) { 463// super(); 464// 465// // 4.0.0.0 XML化に伴いロード先を変更 466// this.edbid = edbid; 467// init( edbid.getMincount(),edbid.getMaxcount(),true,edbid.getPooltime() ); 468// } 469 470 /** 471 * オブジェクトプールから削除するときに呼ばれます。 472 * このメソッドで各オブジェクトごとの終了処理を行います。 473 * 例えば、データベースコネクションであれば、close() 処理などです。 474 * 475 * @og.rev 3.5.4.8 (2004/02/23) SQLException は無視します。 476 * @og.rev 3.5.6.0 (2004/06/18) synchronized を解除します。 477 * 478 * @param obj 終了処理を行うオブジェクト 479 */ 480 @Override 481 protected void objectFinal( final Connection obj ) { 482 Closer.connClose( obj ); 483 } 484 485 /** 486 * コネクションオブジェクトを作成します。 487 * DriverManager.getConnection により作成されたConnection を Connection で 488 * ラッピングします。 489 * Connectionオブジェクトは、close()メソッドで、自分自身を ConnectionFactory の 490 * プールに戻します。 491 * 492 * @og.rev 3.3.3.3 (2003/08/06) コネクションに対して、setTransactionIsolation を、設定しておく。 493 * @og.rev 3.5.2.0 (2003/10/20) 接続情報に、データベース名、ドライバ名情報を追加する。 494 * @og.rev 3.5.6.0 (2004/06/18) synchronized を解除します。 495 * @og.rev 3.8.8.2 (2007/01/26) useAppInfo を設定します。 496 * @og.rev 4.0.0.0 (2007/10/30) 保持情報オブジェクト化に伴う変更 497 * @og.rev 5.1.2.0 (2010/01/01) MySQL対応 明示的に、TRANSACTION_READ_COMMITTED を指定する。 498 * @og.rev 5.5.2.0 (2012/05/01) properties対応 499 * @og.rev 6.3.9.0 (2015/11/06) 内部Propertiesオブジェクトではなく、複製して返します。 500 * @og.rev 7.1.0.0 (2020/01/20) Connection 作成時のタイムアウトを用意します。 501 * @og.rev 5.11.0.0 (2021/05/17) エラーメッセージ出力追加 502 * 503 * @return コネクションオブジェクト 504 */ 505 @Override 506 protected Connection createInstance() { 507 Connection conn = null; 508 try { 509 // DriverManager.setLogWriter( HybsSystem.out ); // ドライバーのログ 510 511 // 5.5.2.0 (2012/05/01) propertyの追加処理と、接続のproperties化 512 // 6.3.9.0 (2015/11/06) 内部Propertiesオブジェクトではなく、複製して返します。 513 // final Properties prop = new Properties (edbid.getProps()); 514 final Properties prop = edbid.getProps(); 515 prop.put ( "user" , edbid.getUser() ); 516 prop.put ( "password", edbid.getPassword() ); 517 518 // 7.1.0.0 (2020/01/20) Connection 作成時のタイムアウトを用意します。 519 // if( TIMEOUT > 0 ) { 520 // DriverManager.setLoginTimeout( TIMEOUT ); 521 // // このExecutorService はConnection を取得する一発物なので、シャットダウンしておく。 522 // final ExecutorService executor = Executors.newSingleThreadExecutor(); // 7.1.0.0 (2020/01/20) 523 // final Future<Connection> future = executor.submit( 524 // new Callable<Connection>() { 525 // @Override 526 // public Connection call() throws SQLException { 527 // return DriverManager.getConnection( edbid.getUrl(), prop ); 528 // } 529 // } 530 // ); 531 // try { 532 // conn = future.get( TIMEOUT, TimeUnit.SECONDS ); 533 // } 534 // finally { 535 // executor.shutdown(); // 正常なシャットダウン 536 // } 537 // } 538 // else { 539 DriverManager.setLoginTimeout( TIMEOUT ); // 7.1.0.0 (2020/01/20) 540 conn = DriverManager.getConnection( edbid.getUrl(), prop ); 541 // } 542 543// conn = DriverManager.getConnection( edbid.getUrl(), prop ); 544 // conn.setReadOnly( true ); 545 conn.setReadOnly( edbid.isReadonly() ); 546 547 conn.setAutoCommit( false ); 548 conn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED); // 初期値 549 // ((OracleConnection)conn).setDefaultExecuteBatch(1); // 初期値 550 // ((OracleConnection)conn).setDefaultRowPrefetch(20); // 初期値 551 552 // 3.5.2.0 (2003/10/20) 接続情報に、データベース名、ドライバ名情報を追加する。 553 // 4.0.0.0 (2007/10/26) 登録先をオブジェクト化 554 if( edbid.getDbProductName() == null ) { 555 final DatabaseMetaData meta = conn.getMetaData(); 556 edbid.setMetaDataInfo( meta ); 557 } 558 return conn ; 559 } 560 catch( final SQLException ex ) { 561 final String errMsg = "コネクトすることが出来ません。" + CR 562 + "DBID=[" + edbid.getDbidKey() + "]" + CR 563 + "URL=[" + edbid.getUrl() + "]" + CR // 5.11.0.0 (2021/05/17) 564 + ex.getMessage() + " , status=" + ex.getSQLState(); 565 Closer.connClose( conn ); 566 throw new OgRuntimeException( errMsg,ex ); // 3.5.5.4 (2004/04/15) 引数の並び順変更 567 } 568 // catch( final InterruptedException | TimeoutException | CancellationException | ExecutionException ex ) { 569 // final String errMsg = "コネクト時にタイムアウトが発生しました。" + CR 570 // + "DBID=[" + edbid.getDbidKey() + "]" ; 571 // Closer.connClose( conn ); 572 // throw new OgRuntimeException( errMsg,ex ); 573 // } 574 } 575 576 /** 577 * アクセスログ取得の為のDBMS_APPLICATION_INFOの使用可否を取得します(初期値:true)。 578 * 579 * データベースへのアクセスログ取得の為、エンジンで接続するコネクションについて 580 * DBMS_APPLICATION_INFO.SET_CLIENT_INFO と SET_MODULE を呼び出しています。 581 * この処理は、ORACLEとの接続のみ有効ですので、接続先データベースが ORACLE 以外は 582 * false を返します。 583 * ORACLE の場合は、システムリソースの USE_DB_APPLICATION_INFO 属性の設定値を 584 * 返します。 585 * この設定値の初期値は、true です。 586 * 587 * @og.rev 3.8.8.2 (2007/01/26) 新規追加 588 * 589 * @return true:使用する/false:使用しない 590 */ 591 public boolean useApplicationInfo() { 592 return edbid.isApplicationInfo(); 593 } 594 595 /** 596 * 接続先のDB名を返します。 597 * 598 * @og.rev 4.3.7.0 (2009/06/01) 新規作成 599 * 600 * @return 接続先のDB名 601 */ 602 public String getDBName() { 603 return edbid.getDbProductName(); 604 } 605 606 /** 607 * 接続先のDBバージョンを返します。 608 * 609 * @og.rev 4.3.7.0 (2009/06/01) 新規作成 610 * 611 * @return 接続先のDBバージョン 612 */ 613 public String getDBVersion() { 614 return edbid.getDbProductVersion(); 615 } 616 617 /** 618 * 接続先の簡易な内部情報を返します。 619 * 620 * @og.rev 5.3.4.0 (2011/04/01) toString() の簡易版 621 * 622 * @return 接続先の簡易な内部情報 623 */ 624 public String dbidInfo() { 625 return edbid.info(); 626 } 627 628 /** 629 * 内部状況を簡易的に表現した文字列を返します。 630 * DBID/URL/USER/プールサイズ を返します。 631 * 632 * @og.rev 3.5.2.0 (2003/10/20) 接続情報に、データベース名、ドライバ名情報を追加する。 633 * @og.rev 3.5.6.6 (2004/08/23) 同期化方法を統一する為、synchronized をつけます。(別途 要検討) 634 * @og.rev 4.0.0.0 (2007/10/29) EDbidのtoStringを呼ぶように変更 635 * 636 * @return このオブジェクトプールの文字列表現 637 * @og.rtnNotNull 638 */ 639 @Override 640 public String toString() { 641 return edbid.toString() + super.toString() ; 642 } 643 644// /** 645// * すべての要素を オブジェクトプールから削除します。 646// * 貸し出し中のオブジェクトは、クリアしません。よって、返り値は、 647// * すべてのオブジェクトをクリアできた場合は、true 、貸し出し中の 648// * オブジェクトが存在した場合(クリアできなかった場合)は、false です。 649// * 650// * @og.rev 6.3.9.0 (2015/11/06) Use block level rather than method level synchronization.(PMD) 651// * @og.rev 7.1.0.0 (2020/01/20) Connection 作成時のタイムアウトを用意します。 652// * 653// * @return すべてクリア(true)/貸し出し中のオブジェクトが残っている(false) 654// */ 655// @Override 656// public boolean clear() { 657// executor.shutdownNow(); 658// return super.clear(); 659// } 660 } 661}