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