I.はじめに
接続プーリングは、ドルイドというように最も身近な例C3P0、DBCP、多くがあります。
MyBatisのは、3つの組み込みのデータ・ソース・タイプをサポートしています。
Pooled:
データソースは、インターフェイスを実装し、アイデアのプールを使用します。UNPooled:
また、DataSourceインタフェースを実現しているが、思考のこのタイプは、プールを使用していませんでした。JDNI:
JDNIサーバー使用する技術が実装され、異なるサーバ間の接続は、同じプールではありません取得します。
注:このプロジェクトは、戦争のウェブやMavenプロジェクトでない場合は、それを使用することはできません。たとえば、Tomcatサーバーは、DBCP接続プールを使用しています。
次のようにどのようにコンフィギュレーション・データ・ソースは、種をMyBatisの:
<!-- 数据库连接池 -->
<dataSource type="POOLED">
<property name="driver" value="${driver}" />
<property name="url" value="${url}" />
<property name="username" value="${username}" />
<property name="password" value="${password}" />
</dataSource>
dataSource属性では、タイプのタグが使用されるデータソースの種類を指定することができます。
二,UnPooled
図1に示すように、接続を取得するために、ソースから始まります。
@Override
public Connection getConnection() throws SQLException {
return doGetConnection(username, password);
}
2、その後、再入力doGetConnection()
プロセス:
private Connection doGetConnection(String username, String password) throws SQLException {
// 实例化一个集合
Properties props = new Properties();
if (driverProperties != null) {
props.putAll(driverProperties);
}
// 判断用户名是否为空
if (username != null) {
props.setProperty("user", username);
}
// 判断密码是否为空
if (password != null) {
props.setProperty("password", password);
}
return doGetConnection(props);
}
図3は、ケースに戻しdoGetConnection()
、オーバーロードされた別の方法を。
private Connection doGetConnection(Properties properties) throws SQLException {
// 初始化
initializeDriver();
// 获取一个连接对象
Connection connection = DriverManager.getConnection(url, properties);
configureConnection(connection);
return connection;
}
4と呼ばれるコードの最初の行、initializeDriver()
方法。
private synchronized void initializeDriver() throws SQLException {
if (!registeredDrivers.containsKey(driver)) {
Class<?> driverType;
try {
if (driverClassLoader != null) {
// 使用反射获取到连接驱动
driverType = Class.forName(driver, true, driverClassLoader);
} else {
driverType = Resources.classForName(driver);
}
// DriverManager requires the driver to be loaded via the system ClassLoader.
// http://www.kfu.com/~nsayer/Java/dyn-jdbc.html
// 实例化连接驱动
Driver driverInstance = (Driver)driverType.newInstance();
// 注册驱动
DriverManager.registerDriver(new DriverProxy(driverInstance));
registeredDrivers.put(driver, driverInstance);
} catch (Exception e) {
throw new SQLException("Error setting driver on UnpooledDataSource. Cause: " + e);
}
}
}
一般的なプロセス:
- 接続オブジェクトを取得しながら、呼び出し
initializeDriver()
接続ドライバを登録されているかどうかを決定する方法。 - 登録ドライブを完了し、使用して
DriverManager.getConnection
接続オブジェクトを取得します。 - 接続にオブジェクト
configureConnection()
方法、自動設定は、トランザクション、およびトランザクション分離レベルをコミット。
private void configureConnection(Connection conn) throws SQLException {
if (autoCommit != null && autoCommit != conn.getAutoCommit()) {
conn.setAutoCommit(autoCommit);
}
if (defaultTransactionIsolationLevel != null) {
conn.setTransactionIsolation(defaultTransactionIsolationLevel);
}
}
このアプローチは、接続プールを考えてきたことではない、またはあなたが頻繁に接続オブジェクトを作成し、破壊した場合、プログラムの効率に影響を与えます。
三、プールされました
のは、接続プールデータソース実装を使用してのアイデアを見てみましょう。
この最初の前には、接続プールが何であるか、接続プールは、接続オブジェクトを格納するための容器であることです。コンテナはつまり、2つのスレッドが同じ接続オブジェクトを取得することはできません、収集され、スレッドセーフでなければなりません。FIFOの原則:しかし、また、特性キューを持っています。
接続プールを使用する利点は:作成し、頻繁避け、データベース接続に起因するオーバーヘッドを閉じ、システムリソースを節約します。
1、接続を取得するためにソースコードの先頭で始まります。
@Override
public Connection getConnection() throws SQLException {
return popConnection(dataSource.getUsername(), dataSource.getPassword()).getProxyConnection();
}
2、呼び出しpopConnection()
(ビット長)メソッド。
private PooledConnection popConnection(String username, String password) throws SQLException {
boolean countedWait = false;
PooledConnection conn = null;
long t = System.currentTimeMillis();
int localBadConnectionCount = 0;
while (conn == null) {
synchronized (state) {
if (!state.idleConnections.isEmpty()) {
// Pool has available connection
conn = state.idleConnections.remove(0);
if (log.isDebugEnabled()) {
log.debug("Checked out connection " + conn.getRealHashCode() + " from pool.");
}
} else {
// Pool does not have available connection
if (state.activeConnections.size() < poolMaximumActiveConnections) {
// Can create new connection
conn = new PooledConnection(dataSource.getConnection(), this);
if (log.isDebugEnabled()) {
log.debug("Created connection " + conn.getRealHashCode() + ".");
}
} else {
// Cannot create new connection
PooledConnection oldestActiveConnection = state.activeConnections.get(0);
long longestCheckoutTime = oldestActiveConnection.getCheckoutTime();
if (longestCheckoutTime > poolMaximumCheckoutTime) {
// Can claim overdue connection
state.claimedOverdueConnectionCount++;
state.accumulatedCheckoutTimeOfOverdueConnections += longestCheckoutTime;
state.accumulatedCheckoutTime += longestCheckoutTime;
state.activeConnections.remove(oldestActiveConnection);
if (!oldestActiveConnection.getRealConnection().getAutoCommit()) {
try {
oldestActiveConnection.getRealConnection().rollback();
} catch (SQLException e) {
log.debug("Bad connection. Could not roll back");
}
}
conn = new PooledConnection(oldestActiveConnection.getRealConnection(), this);
conn.setCreatedTimestamp(oldestActiveConnection.getCreatedTimestamp());
conn.setLastUsedTimestamp(oldestActiveConnection.getLastUsedTimestamp());
oldestActiveConnection.invalidate();
if (log.isDebugEnabled()) {
log.debug("Claimed overdue connection " + conn.getRealHashCode() + ".");
}
} else {
// Must wait
try {
if (!countedWait) {
state.hadToWaitCount++;
countedWait = true;
}
if (log.isDebugEnabled()) {
log.debug("Waiting as long as " + poolTimeToWait + " milliseconds for connection.");
}
long wt = System.currentTimeMillis();
state.wait(poolTimeToWait);
state.accumulatedWaitTime += System.currentTimeMillis() - wt;
} catch (InterruptedException e) {
break;
}
}
}
}
if (conn != null) {
// ping to server and check the connection is valid or not
if (conn.isValid()) {
if (!conn.getRealConnection().getAutoCommit()) {
conn.getRealConnection().rollback();
}
conn.setConnectionTypeCode(assembleConnectionTypeCode(dataSource.getUrl(), username, password));
conn.setCheckoutTimestamp(System.currentTimeMillis());
conn.setLastUsedTimestamp(System.currentTimeMillis());
state.activeConnections.add(conn);
state.requestCount++;
state.accumulatedRequestTime += System.currentTimeMillis() - t;
} else {
if (log.isDebugEnabled()) {
log.debug("A bad connection (" + conn.getRealHashCode() + ") was returned from the pool, getting another connection.");
}
state.badConnectionCount++;
localBadConnectionCount++;
conn = null;
if (localBadConnectionCount > (poolMaximumIdleConnections + poolMaximumLocalBadConnectionTolerance)) {
if (log.isDebugEnabled()) {
log.debug("PooledDataSource: Could not get a good connection to the database.");
}
throw new SQLException("PooledDataSource: Could not get a good connection to the database.");
}
}
}
}
}
if (conn == null) {
if (log.isDebugEnabled()) {
log.debug("PooledDataSource: Unknown severe error condition. The connection pool returned a null connection.");
}
throw new SQLException("PooledDataSource: Unknown severe error condition. The connection pool returned a null connection.");
}
return conn;
}
分析:
アイドル接続オブジェクトがプールに接続されているがあるかどうか1が、それが決定され、直接そこに返されます。
図2に示すように、接続はアイドル接続プールではなく、最初のアクティブな接続のプールは、データベース接続ベアラの最大数未満であるか否かを判断した場合、新しい接続オブジェクトを再作成するよりも小さいです。
3が、接続プールがベアラの最大数に達した場合には、接続プールの着信接続(最も古い)の最初のアウトプットを返します。
IVの概要
JDNIブログが明確でないため、共有使用しないことについて、私は実装の研究の詳細内側には行かなかったが、後者はそれを補完する必要があります。
さらに約MyBatisのは、2つのデータソースを使用して何もオーバー締結し、その主な考えは、プールだけでなく、コネクションプーリングをもたらし使用する利点についてです。
ウェルカムメッセージの修正を配置しない場合は最後に、上記では、自習の要約です。
読んでくれてありがとう!