1

我已经实现了一个连接池。一切都很好。现在,如果客户端借用了一个连接,甚至将其返回到池中,但客户端还保留了该连接的引用。现在,如果池返回相同的连接到另一个客户端;这将导致多人使用相同的连接。

我怎样才能避免这种情况?

4

1 回答 1

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 - 客户端代码可能想要捕获池连接不再有效的情况)或其他情况:-)

上述代码的另外两个问题 - 用于保护仅对池代码可用的方法的包访问不是很健壮。也许您可以将 MyConnection 代码创建为池代码中的某种内部类。最后,必须重写所有java.sql.Connection 接口会很痛苦。

}

于 2013-02-06T10:42:08.543 回答