読者です 読者をやめる 読者になる 読者になる

ぺーぺーSEのブログ

備忘録・メモ用サイト。

Java、データベース接続(Commons DBCP、c3p0も含め)

Java Commons DBCP c3p0

JavaJDBCをつかったDB接続

参照系

// PostgreSQL JDBC Driverのロード
Class.forName("org.postgresql.Driver");

Connection conn = null;
Statement stmt = null;
try {
  // 接続
  conn = DriverManager.getConnection("jdbc:postgresql://localhost:5432/TestDB", "username", "password");
  // ステートメントを作成
  stmt = conn.createStatement();
  // 問合せの実行
  ResultSet rset = stmt.executeQuery("select param1, param2 from test");
  // 問合せ結果の表示
  while (rset.next()) {
      // 列番号による指定
      System.out.println(rset.getString(1) + "\t" + rset.getString(2));
  }
  stmt.close();
  conn.close();
} catch (SQLException e) {
  e.printStackTrace();
} finally {
  // 保険に
  if(stmt !=null && !stmt.isClosed()) {
    stmt.close();
  }
  if(conn !=null && !conn.isClosed()) {
    conn.close();
  }
}
  • Class.forName
    • クラスをロードする。
  • conn = DriverManager.getConnection
    • 「Class.forName」でロードされたJDBCドライバを使用して、データベースとのコネクションを確立する。
    • 超遅い(0.1秒くらい)らしい。なので通常はコネクションオブジェクトを複数作成してプールする(後述)。
  • ResultSet rset = stmt.executeQuery("select param1, param2 from test");
    • 参照系のクエリを実行する際は「executeQuery」。

更新系

// PostgreSQL JDBC Driverのロード
Class.forName("org.postgresql.Driver");
try {
  // 接続
  Connection conn = DriverManager.getConnection("jdbc:postgresql://localhost:5432/TestDB", "username", "password");
  // オートコミットをオフ
  conn.setAutoCommit(false);
  // ステートメントを作成
  Statement stmt = conn.createStatement();
  // 問合せの実行
  int insertNum = stmt.executeUpdate("insert into test values(〜");
  // コミット
  conn.commit();
} catch (SQLException e) {
  // 更新に失敗したのでロールバック
  conn.rollback();
  e.printStackTrace();
} finally {
  if(stmt !=null && !stmt.isClosed()) {
    stmt.close();
  }
  if(conn !=null && !conn.isClosed()) {
    conn.close();
  }
}
  • ResultSet rset = stmt.executeUpdate("insert into test values(〜");
    • 更新系のクエリを実行する際は「executeQuery」。
  • conn.rollback();
    • 更新系の処理では、複数回更新処理を行った後、途中で例外は発生した際にロールバックを行い、全てのデータ更新を無効化する。
    • 全て無効化したくない場合は更新処理の途中で「begin」クエリを発行するとそこからトランザクションの開始を明示でき、「rollback」を実行すると「begin」発行直後までのデータ更新を無効化する。

Commons DBCP

DBCPはDataBase Connection Poolingの略だと思う。

ちょっとデータソースファクトリーというのを使ってみる。

Properties properties = new Properties();
InputStream is = ClassLoader.getSystemResourceAsStream("dbcp.properties");
properties.load(is);
DataSource ds = BasicDataSourceFactory.createDataSource(properties);
Connection con = ds.getConnection();
// con.close();

「con.close();」を叩いちゃったら、DBPCで管理しているコネクションを破棄してしまうように見えるが「ds.getConnection()」で取得したConnectionオブジェクトはJDBCの「java.sql.Connection」実装クラスをさらにラップしており、実際にはコネクションが解放される訳ではなく、プールに戻ってる模様。
・dbcp.properties

driverClassName=org.postgresql.Driver
url=jdbc:postgresql://localhost:5432/TestDB
username=username
password=password
initialSize=30
maxActive=100
maxIdle=30
maxWait=5000
validationQuery=select count(*) from test

ベーシックデータソースというのを使ってみる。

BasicDataSource basicDataSource = new BasicDataSource();
basicDataSource.setDriverClassName(“org.postgresql.Driver”);
String url = new StringBuffer(“jdbc:postgresql://”).append(”localhost:5432/TestDB”).toString();
basicDataSource.setUrl(url);
/* データベースのユーザー名 */
basicDataSource.setUsername(“username”);
/* データベースのパスワード */
basicDataSource.setPassword(“password”);
/* データベース最大接続数 */
basicDataSource.setMaxActive(100);

dataSource = (DataSource) basicDataSource;
基本設定
  • username
    • DB接続ユーザ名
  • password
    • DB接続パスワード
  • url
  • driverClassName
    • 使用するJDBCドライバクラスのフルネーム
  • connectionProperties
    • 接続に必要なプロパティを記述
プロパティ名(1)=プロパティ値(1);プロパティ名(2)=プロパティ値(2);
接続設定
  • defaultAutoCommit
    • オートコミットモードの初期値を指定(デフォルト:true)
  • defaultReadOnly
    • リードオンリーモードの初期値を指定(デフォルトはJDBCドライバ依存)
  • defaultTransactionIsolation
    • TransactionIsolationレベルの初期値を指定(デフォルトはJDBCドライバ依存)
    • TRANSACTION_NONE, READ_COMMITTED, READ_UNCOMMITTED, REPEATABLE_READ, SERIALIZABLE
  • defaultCatalog
    • デフォルトのカタログ名を指定
コネクションプール設定
  • initialSize
    • コネクションプールの初期コネクションの数(デフォルト:0)
  • maxActive
    • 最大Activeコネクション数(デフォルト:8)
    • Activeコネクションとはコネクションプールから業務ロジックにより取得されたコネクションの数(Begin-Tranしてるコネクションの数)
  • maxIdle
    • 最大Idleコネクション数(デフォルト:8)
    • Idleコネクションとは業務ロジックで使用されていないプールされたコネクションのこと
    • つまりアプリケーション全体でDBへ張っているコネクション数は最大「maxActive + maxIdle」となる可能性がある?
    • コネクションがコネクションプールに返却される際、コネクションプールのサイズがmaxIdle以上の場合、コネクションはプールへ返却されずに解放される
    • 負の値を指定すると無制限(一度確立したコネクションは解放されることはない)
  • maxWait
    • コネクション取得の待ち時間(デフォルト:-1(永久に待つ))
    • プールされているコネクションが存在しない場合、プールにコネクションが返却されるのを待つ時間
  • validationQuery
    • コネクションが利用可能か検証するためのSQL
    • 「testOnBorrow」「testOnReturn」「コネクション監視スレッド設定」にて使用される
    • MySQLの例)SELECT 1
  • testOnBorrow
    • プールからコネクションを取得する前に有効性の確認をする設定(デフォルト:true)
    • 「validationQuery」が指定されていない場合はfalse
    • 有効性が確認できない場合は「SQLException」が投げられる
  • testOnReturn
    • プールへコネクションを返す前に有効性の確認をする設定(デフォルト:false)
    • 「validationQuery」が指定されていない場合はfalse
    • 有効性が確認できない場合はコネクションが破棄される
  • connectionInitSqls
    • ConnectionFactoryがコネクションを初回作成した際に使用されるvalidate用のSQL
コネクション監視スレッド設定
  • timeBetweenEvictionRunsMillis
    • プール内のIdleコネクションを指定時間間隔で監視(デフォルト:-1ms)
    • 0以下の値では監視スレッドは起動しない
    • 監視スレッドは以下の処理を行う
      • Idleコネクションの確保(minIdleの設定分確保)
      • Idleコネクションの有効性の確認(testWhileIdleがtrueの時のみ有効)
      • Idleコネクションの生存期間の確認(minEvictableIdleTimeMillisにて設定)
  • minIdle
    • 最少Idleコネクション数(デフォルト:0)
    • 「timeBetweenEvictionRunsMillis」が1以上の場合のみ有効
  • testWhileIdle
    • Idleコネクションの有効性の確認(デフォルト:false)
    • 「validationQuery」が指定されていない場合はfalse
    • 「timeBetweenEvictionRunsMillis」の時間毎に最大「numTestsPerEvictionRun」件の確認用SQLが発行される
  • minEvictableIdleTimeMillis
    • Idleコネクションの生存期間(デフォルト:30*60*1000ms)
    • 「timeBetweenEvictionRunsMillis」が1以上の場合のみ有効
    • 指定した期間Idleコネクションが使用されなかった場合削除される
  • numTestsPerEvictionRun
    • 1回の監視処理でチェックするIdleコネクション(プールされているコネクション)の最大数(デフォルト:3)
    • 「timeBetweenEvictionRunsMillis」が1以上の場合のみ有効
    • 負の値を設定した場合、Idleコネクション数の「何分の一をチェックする」という割合で指定可能
      • 「-3」→1/3、「-2」→1/2
接続リーク対策
  • removeAbandoned(デフォルト:false)
    • true の場合、close()されなかった接続を回収する
  • removeAbandonedTimeout(デフォルト:300s)
    • makeObject()またはborrowObject()してからremoveAbandonedTimeout秒経過した接続を、close() されなかったと見なす
    • 処理に時間の掛る SQL を実行する場合には注意が必要
  • logAbandoned(デフォルト:false)
Prepared Statement設定
  • poolPreparedStatements
    • Prepared Statementのプーリングを有効か指定(デフォルト:false)
  • maxOpenPreparedStatements
    • プール内に保管する最大Prepared Statement数を指定(デフォルト:0(無制限))
Commons DBCP個人的神サイト

http://www.ksky.ne.jp/~snbhsmt/commons-dbcp.html
http://www.limy.org/program/java/commons_dbcp.html

c3p0

Commons DBCP以外にもある。
以下設定メモ。

コネクションプールの基本設定
  • acquireIncrement
    • デフォルト:3
    • 接続プールが使い尽くしたとき、一回同時に新たに取得するコネクション数
  • initialPoolSize
    • デフォルト:3
    • 初期状態のコネクション数。minPoolSize と maxPoolSizeの間の数字で設定する必要がある。
  • maxPoolSize
    • デフォルト:15
    • 接続プールに保持できる最大コネクション数
  • maxIdleTime
    • デフォルト:0 (s) ※0は永久に残ることを意味する
    • 使用されないコネクションが生存する時間
  • minPoolSize
    • デフォルト:3
    • 接続プールに保持する最小コネクション数。
コネクションプールサイズと生存期間の設定
  • maxConnectionAge
    • デフォルト:0 (s) ※0は永久に残ることを意味する
    • 接続プール内のコネクションの生存期間。生存期間外のコネクションが破棄される
  • maxIdleTime
    • デフォルト:0 (s)
    • 最大アイドル時間。指定される時間内で使用されていなければコネクションが破棄されます。
    • maxConnectionAgeとの違いは、maxConnectionAgeは絶対時間を指定するのに対し、maxIdleTimeは相対時間を指定
  • maxIdleTimeExcessConnections
コネクションの確認を行う設定
  • automaticTestTable
    • デフォルト:null
    • 接続テスト用テーブル名
      • c3p0は自動的に指定される名前のテーブルを生成し、接続を行う際に、このテーブルを用いてテストを行う
      • また、automaticTestTableが設定される場合、c3p0はテスト用クエリ語句を自動的生成し、preferredTestQuery設定が無視される
  • connectionTesterClassName
    • デフォルト:com.mchange.v2.c3p0.impl.DefaultConnectionTester
    • 接続テストクラス。 ConnectionTesterまたはQueryConnectionTesterインタフェースを実装する必要がある。
    • また、デフォルトのテスタークラスでテストで使用するクエリは「preferredTestQuery」にて設定する
  • idleConnectionTestPeriod
    • デフォルト:0 (s) ※0はチェックしないことを意味する
    • 接続プール内のアイドル状態のコネクションを時間間隔「0以外の数字」でチェックする
  • preferredTestQuery
    • デフォルト:null
    • デフォルトのConnectionTester(ConnectionTesterClassのデフォルト設定)を使用してコネクションを確認するためのクエリを定義
  • testConnectionOnCheckin
    • デフォルト:false
    • trueの場合、コネクション利用開始時にコネクションの有効性を確認する
  • testConnectionOnCheckout
    • デフォルト:false
    • trueの場合、コネクション利用終了時にコネクションの有効性を確認する
ステートメントプールの設定
  • maxStatements
    • デフォルト:0
    • c3p0のグローバルPreparedStatementキャッシュ・サイズ
    • maxStatementsとmaxStatementsPerConnectionともに0の場合、statementキャッシュは無効。
    • maxStatementsは全コネクションのStatementsキャッシュの数を定義するため、アプリケーション全体で頻繁に使用されるPreparedStatementsの数×maxPoolSize で得られる数値を設定すれば妥当。
  • maxStatementsPerConnection
    • デフォルト:0
    • c3p0個々のコネクションPreparedStatementsキャッシュ・サイズ。
    • アプリケーションのdistinct PreparedStatementsの数+2,3が妥当。
  • statementCacheNumDeferredCloseThreads
DB接続障害からの復旧設定
  • acquireRetryAttempts
    • デフォルト:30
    • 新たにコネクションを取得するのに失敗したときのリトライ回数
  • acquireRetryDelay
    • デフォルト:1000 (ms)
    • リトライ間隔時間
  • breakAfterAcquireFailure
    • デフォルト:false
    • true:コネクションの取得ができなかった場合、DataSource自体は閉鎖され、接続不可になる
    • false:コネクションの取得ができなかった場合、すべてのスレッドにExceptionを投げるが、DataSourceは有効のままで保持し続き、次回のgetConnection()の時も、新たなコネクションの取得を試みる
カスタマイズによるコネクションライフサイクルの管理設定
  • connectionCustomizerClassName
    • デフォルト:null
    • コネクション拡張クラス。ConnectionCustomizerインタフェースを実装したフルパスのクラス名を指定する。
トランザクションのハンドリング設定
  • autoCommitOnClose
    • デフォルト:false(ロールバックする)
    • コネクションをクローズするとき、すべての未確定の操作をコミットするかどうかを設定
  • forceIgnoreUnresolvedTransactions
アプリケーション故障時のデバックと回避の設定
  • debugUnreturnedConnectionStackTraces
  • unreturnedConnectionTimeout
その他データソースの設定
  • checkoutTimeout
    • デフォルト:0 (ms) ※0は無期限に待つことを意味する
    • プールが使い尽くされている場合のコネクションの最大待つ時間。タイムアウト時SQLExceptionが投げ出される
  • factoryClassLocation
  • maxAdministrativeTaskTime
  • numHelperThreads
    • デフォルト:3
    • c3p0 は非同期操作をサポートし、遅いJDBC操作はヘルパースレッドによって実行さる。
    • 複数のスレッドにより複数の操作を同時に実行することで、パフォーマンスを向上させることがでる。
  • usesTraditionalReflectiveProxies