接続プールを実装しました。すべてが良いです。クライアントが接続を借用し、それをプールに返す場合でも、クライアントはこの接続の参照を保持します。ここで、プールが同じ接続を別のクライアントに返す場合。これにより、複数の人が同じ接続を使用することになります。
どうすればそれを回避できますか?
接続プールを実装しました。すべてが良いです。クライアントが接続を借用し、それをプールに返す場合でも、クライアントはこの接続の参照を保持します。ここで、プールが同じ接続を別のクライアントに返す場合。これにより、複数の人が同じ接続を使用することになります。
どうすればそれを回避できますか?
基礎となる接続オブジェクトを返すのではなく、それをラップする別のオブジェクトを返します。そのオブジェクト内に (ある種のプライベート プロパティを使用して) そのオブジェクトの状態を格納します。まだ使用できるか、またはプールに戻されたり、タイムアウトなどのその他の条件によって無効になったりしていますか)。次に、それを使用しようとするメソッド呼び出しをインターセプトし、その状態をチェックできます。使用できなくなった場合は、例外をスローします。
クライアントが直接アクセスできないように、ラップされた接続オブジェクトもプライベートである必要があります。
クライアントごとに 1 つのラッパーがありますが、2 つ以上のラッパーが基になる接続オブジェクトを共有する場合があります。ただし、クライアントごとに状態を保存しているため、一度にオブジェクトを使用できるクライアントは 1 つだけです。
テストされていない例を含めるように編集しました。これは、私のアプローチに大きな問題があることを示しています。
java.sql.Connection を実装するものを返すと仮定すると、以下のクラスのインスタンスを返すことができます。
package same.package.as.your.pool; // so your pool has access to set isValidConnection
import java.sql.Connection;
class MyConnection implements Connection {
private Connection actualConnection;
private boolean isValidConnection = false;
MyConnection(Connection conn) {
// package acccess for pool class to create connection
actualConnection = conn;
isValidConnection = true;
}
public boolean getIsValidConnection() {
return isValidConnection;
}
void setIsValidConnection(boolean isValid) {
// pool class can call this to invalidate when returned to pool or timed out
isValidConnection = isValid;
}
// intercept java.sql.Connection methods, checking if connection is still valid first
// for example
PreparedStatement prepareStatement(String sql) {
if (! isValidConnection) {
// WHAT TO DO HERE?
}
return actualConnection.prepareStatement(sql);
}
// ... and the rest
最初の大きな問題は、プールに返されたために接続が無効になったときに、prepareStatement などのメソッドから例外をスローするのが理想的です。ただし、元のインターフェイスのキャッチされた例外 (この場合は SQLException をスローする) によって制約されるため、SQLException (yuk、実際には SQLException ではありません) またはキャッチされていない例外 (yuk - クライアント コード) をスローする必要があります。おそらく、プールされた接続が有効でなくなった場合をキャッチしたいでしょう)または何か他のもの:-)
上記のコードに関する他の 2 つの問題 - プール コードでのみ使用できるようにするメソッドを保護するためのパッケージ アクセスは、あまり堅牢ではありません。おそらく、プール コード内の何らかの内部クラスとして MyConnection コードを作成できます。最後に、すべてのjava.sql.Connection インターフェースをオーバーライドしなければならないのは面倒です。
}