【问题标题】:Database connection management in SpringSpring中的数据库连接管理
【发布时间】:2010-02-12 06:15:05
【问题描述】:

在使用 Spring Framework 时,我们是否必须显式管理数据库资源。喜欢关闭所有打开的连接等?

我读到 Spring 将开发人员从这种样板编码中解脱出来......

这是为了回答我在 Spring Web 应用程序中遇到的错误:

org.springframework.jdbc.CannotGetJdbcConnectionException: 无法获得 JDBC 连接;嵌套的 例外是 java.sql.SQLException: ORA-00020: 最大进程数 (150) 超出

jdbcTemplate 配置在 xml 文件中,DAO 实现引用了这个用于查询数据库的jdbcTemplate bean。

【问题讨论】:

标签: java database spring


【解决方案1】:

在使用 Spring Framework 时,我们是否必须显式管理数据库资源,例如关闭所有打开的连接等?

如果您使用 JbdcTemplate 之类的 Spring 抽象,Spring 会为您处理,并且极不可能在该部分中存在错误。

现在,如果没有关于您的配置(您的 applicationContext.xml)、上下文(您如何创建应用程序上下文,具体何时发生?)的更多信息,很难说什么。所以这是在黑暗中拍摄:您是否在数据源配置中设置了属性destroy-method="close"?类似的东西:

 <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">

在某些情况下,不使用销毁方法并结合其他一些不良做法最终可能会耗尽资源。

【讨论】:

    【解决方案2】:

    这可能是由于连接未关闭。您如何在春季访问您的连接?您是否正在使用 JdbcTemplate 来查询数据库?还是只是从 spring 中获取连接?

    【讨论】:

      【解决方案3】:

      我读到春天可以缓解 来自此类样板的开发人员 编码

      这取决于您操作的 Spring 级别。 JdbcTemplate 提供了许多不同的操作,其中一些是即发即弃的,其中一些仍然需要您正确管理 JDBC 资源(连接、结果集、语句等)。经验法则是,如果您发现自己拨打了getConnection(),那么在某些时候您还需要拨打releaseConnection()

      ORA-00020: 最大进程数 (150) 超出

      您使用的是连接池吗?如果是这样,请确保它没有配置比您的数据库能够处理的最大连接数(在这种情况下为 150)更大的连接数。如果您不使用连接池,那么您真的应该使用。

      【讨论】:

        【解决方案4】:

        您说“在 xml 文件中配置了 jdbcTemplate”。您通常应该为每次使用创建一个新的 jdbcTemplate 实例,而不是由 spring 管理。

        我猜每次你从spring请求一个新的jdbcTemplate bean时,它都会创建一个新的与数据库的新连接,但是在它超出你的代码范围之后它仍然被spring的applicationContext引用,所以不会关闭连接。

        【讨论】:

        • 连接在查询/执行/更新结束时关闭。否则它必须有自己的 close 方法,这会破坏它的一些目标。所以将它作为 Spring Bean 应该是完全可以的
        【解决方案5】:

        我的软管,只提供 20 个连接。我通过手动关闭对 db 的每个请求的连接来完成。我没有在 bean 中声明 destory-method(这不起作用“我不知道为什么”),但我在每个请求调用中都完成了。 (提示:在 dao 类中扩展 JdbcDaoSupport)。

        public void cleanUp() {
                try {
                    if (!this.getJdbcTemplate().getDataSource().getConnection().isClosed()) {
                        this.getJdbcTemplate().getDataSource().getConnection().close();
                    }
                } catch (Exception e) {
                    Logger.getLogger(myDAOImpl.class.getName()).log(Level.SEVERE, null, e);
                }
            }
        

        重要提示:我在这里提到,我为解决我的问题所做的工作。您不应直接使用此代码。您应该只使用一个连接。根据您的代码更改 if

        【讨论】:

        • 我提到对我不起作用的销毁方法是我的 daoclass 而不是 **datasource
        • 我知道这是一个非常古老的答案,但复制它是一个非常危险的答案:Spring 中 DataSource 接口的大多数(如果不是全部?)实现在每次调用 @987654322 时都会返回一个新连接@ 所以这段代码只会让事情变得更糟:它会首先获得 1 个新连接并检查它是否已关闭(当然不是,您刚刚打开它)然后它会打开另一个新连接并立即关闭它。根本不做任何清理,只是在尝试时又泄漏了 1 个连接。警告:请勿复制或使用此代码!
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-08-17
        • 2019-02-04
        • 2019-05-11
        • 2021-02-18
        • 2014-11-13
        • 1970-01-01
        相关资源
        最近更新 更多