package java.common;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Vector;
/**
* DBコネクション管理クラス
*
*/
public class DBConnectionPool
{
/** インスタンス */
private static DBConnectionPool connectionPool = null;
/** コネクションを保持するベクトル */
private Vector connections = null;
/** 現在のコネクション数 */
int currentCount = 0;
/** 同時にデータベースに接続可能なコネクション数 */
private static final int MAX_CONNECTION = Integer.parseInt(SystemProperties.get( "MAX_CONNECTION" ));
/** 最小コネクション数 */
private static final int MIN_CONNECTION = Integer.parseInt(SystemProperties.get( "MIN_CONNECTION" ));
/** 最大待ち時間(秒)*/
private static final int CONNECTION_TIMEOUT = Integer.parseInt(SystemProperties.get( "CONNECTION_TIMEOUT" ));
/** コネクション取得待ち時間(ミリ秒) */
private static final int WAIT_TIME = Integer.parseInt(SystemProperties.get( "WAIT_TIME" ));
/** DBアクセスに必要な各値(環境に依存) */
private static final String DRIVER = SystemProperties.get( "DRIVER_CLASS_NAME" );
private static final String URL = SystemProperties.get( "URL" );
private static final String USER = SystemProperties.get( "USER" );
private static final String PASSWORD = SystemProperties.get( "PASSWORD" );
/**
* DBConnectionPool インスタンスの取得
*
* @return インスタンスを戻します。
*/
public static DBConnectionPool getInstance() throws Exception
{
if( DBConnectionPool.connectionPool == null || !DBConnectionPool.checkConnectionValidity() )
{
DBConnectionPool.connectionPool = new DBConnectionPool();
}
return DBConnectionPool.connectionPool;
}
/**
* DBConnectionPool インスタンスの生成
* ※privateなので、外部からの生成(new)は不可能
*/
private DBConnectionPool() throws Exception
{
// DBアクセスに必要な各値を設定
Class.forName( DRIVER );
connections = new Vector();
for( int i = 0; i < MIN_CONNECTION; i++ )
{
Connection connection = createConnection();
connections.add( connection );
currentCount++;
}
}
/**
* コネクションの取得
* ※取得できない場合は引数で与えられた回数だけコネクション取得待ち時間おきにトライ
*
* @param count_ コネクション取得の試行回数。
* @return コネクション(取得できなかったた場合はnul)を戻します。
* @throws SQLException
*/
public synchronized Connection getConnection( int count_ ) throws SQLException
{
// 試行回数に達した場合は null を返す
if( count_ < 1 )
{
return null;
}
// コネクションが残っていればプールから1つ取り出して提供する
if( 0 < connections.size() )
{
Connection connection = ( Connection )connections.get( 0 );
connections.remove( 0 );
return connection;
}
else if( currentCount < MAX_CONNECTION )
{
currentCount++;
return createConnection();
}
else
{
// コネクションが残っていなければXXミリ秒待機
try
{
wait( WAIT_TIME );
}
catch( Exception e )
{
e.printStackTrace();
}
// 試行回数を1つ減らして再度取得を実行
return getConnection( count_ - 1 );
}
}
/**
* コネクションの返却
*
* @param connection_ 返却するコネクション。
*/
public synchronized void releaseConnection( Connection connection_ )
{
// プールに返されたコネクションを追加
connections.add( connection_ );
}
/**
* コネクションの作成
*
* @return conn コネクション。
* @throws SQLException
*/
private Connection createConnection() throws SQLException
{
// 最大待ち時間を設定
DriverManager.setLoginTimeout( CONNECTION_TIMEOUT );
Connection conn = DriverManager.getConnection( URL, USER, PASSWORD );
return conn;
}
/**
* コネクションの有効性チェック
*
* @return trueOrFalse 真偽。
*/
private static boolean checkConnectionValidity()
{
boolean trueOrFalse = true; //戻り値
String validationQuery = "select 1"; //検証用クエリ
Connection conn = null;
Statement stmt = null;
try
{
// プールされているコネクションで検証用クエリを実行
if( 0 < connectionPool.connections.size() )
{
conn = ( Connection )connectionPool.connections.get( 0 );
connectionPool.connections.remove( 0 );
stmt = conn.createStatement();
stmt.execute( validationQuery );
}
}
catch( SQLException e )
{
// 接続エラーが発生した場合は戻り値をfalseとする
if( e.getErrorCode() == 0 && "08S01".equals( e.getSQLState() ) )
{
trueOrFalse = false;
}
}
finally
{
if( stmt != null )
{
try
{
stmt.close();
}
catch( SQLException e )
{
}
}
if( conn != null )
{
connectionPool.releaseConnection( conn );
}
}
return trueOrFalse;
}
/**
* プールされているコネクションのクローズ
*
*/
public synchronized void closeConnections()
{
Connection connection = null;
// プールからコネクションを取り出してクローズ
while( 0 < connections.size() )
{
connection = ( Connection )connections.get( 0 );
connections.remove( 0 );
if( connection != null )
{
try
{
connection.close();
connection = null;
}
catch( SQLException e )
{
// 特に何もしない
System.out.println( "DBコネクションのクローズに失敗" );
}
}
}
}
}