Java Oracle连接池 - 已关闭连接异常

时间:2010-06-29 20:38:23

标签: java oracle jdbc connection-pooling

这篇文章不仅仅是一个问题,更是对我正确行事的确认。我看过很多类似的帖子,但我不确定我是否完全理解所说的一切。

问题是,经过一段时间后,我在尝试建立与oracle数据库的连接时遇到异常。 (我正在使用Tomcat 6.0和Spring)

以前我有以下配置:

private PoolDataSource poolDataSource = null;

public MainDAOImpl(String url, String username, String password)
        throws Exception
{
    poolDataSource = PoolDataSourceFactory.getPoolDataSource();

    try
    {
        poolDataSource.setConnectionFactoryClassName("oracle.jdbc.pool.OracleDataSource");
        poolDataSource.setURL(url);
        poolDataSource.setUser(username);
        poolDataSource.setPassword(password);
    }
    catch( SQLException e )
    {
        ...
    }
}

public List<Object> getValues(String query)
{
    Connection connection = null;
    PreparedStatement preparedStatement = null;

    try
    {
        connection = poolDataSource.getConnection();
        preparedStatement = connection.prepareStatement(query);

        ...
    }
    catch( SQLException e )
    {
        ...
    }
    finally
    {
        //close connections
    }
}

但是,有时preparedStatement = connection.prepareStatement(query);会抛出一个带有“已关闭异常”消息的SQLException。

值得注意的是,每次服务器重启时,MainDAOImpl的构造函数只被调用一次(它是通过Spring注入的依赖项)。

我最近改变了我的设置:

private DataSource dataSource = null;

public MainDAOImpl()
        throws Exception
{
    try
    {
        Context initContext = new InitialContext();
        Context envContext = (Context)initContext.lookup("java:/comp/env");
        dataSource = (DataSource)envContext.lookup("jdbc/myOracleConn");
    }
    catch( NamingException e )
    {
        ...
    }
}

poolDataSource.getConnection()dataSource.getConnection()

我还在Tomcat的上下文中添加了以下资源:

<Resource name="jdbc/myOracleConn" auth="Container"
          type="javax.sql.DataSource"
          driverClassName="oracle.jdbc.OracleDriver"
          url="<myURL>"
          username="<myUsername>" password="<myPassword>"
          maxActive="20" maxIdle="10" maxWaith="-1" />

这基本上遵循http://tomcat.apache.org/tomcat-6.0-doc/jndi-datasource-examples-howto.html逐字逐句。

一切似乎都在发挥作用。我的问题是,这些更改是否会解决我的封闭式连接问题,还是我需要做一些不同的事情?

谢谢,

B.J。

1 个答案:

答案 0 :(得分:1)

首先,如果您使用Spring进行依赖注入,我建议您也使用DI将DAO的依赖项注入其中。

换句话说,您的DAO应该有一个DataSource注入其中,而不是DAO实现知道1)要构造什么类型的DataSource或2)在JNDI中查找它的方式和位置。春天can handle JNDI lookups适合你。

我还建议使用Spring的JdbcTemplate,因为它可以自己创建一个比原始JDBC调用更好的包装。

最后,您获得的实际异常可能只是因为数据库服务器正在关闭长打开连接。不确定您正在使用哪个连接池实现,但是在commons-dbcp中,在返回连接之前池将执行an option for a "validationQuery"以验证连接是否仍然有效。我相信大多数其他游泳池都提供类似的功能,我建议这样做 - 这样你的DAO永远不会从游泳池接收过时的连接。