避免客户端在实现连接池时保持连接的引用

时间:2013-02-06 10:30:43

标签: java connection-pooling

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

我该如何避免?

1 个答案:

答案 0 :(得分: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这样的方法中抛出一个Exception,因为它已被返回到池中。但是因为你受到原始接口的捕获异常的限制(在这种情况下,抛出SQLException)你需要抛出一个SQLException(yuk,它实际上不是一个SQLException)或一个未捕获的异常(yuk - 客户端代码)可能想要捕捉汇集连接不再有效的情况)或其他: - )

上面代码的另外两个问题 - 用于保护仅适用于池代码的方法的包访问不是很强大。也许您可以将MyConnection代码创建为池代码中的某种内部类。最后,必须覆盖所有 java.sql.Connection接口将是一件痛苦的事。

}