【问题标题】:Spring Data DB Connection ManagementSpring Data 数据库连接管理
【发布时间】:2016-08-27 15:05:43
【问题描述】:

如果我调用 Spring Repository 方法来查询 DB,Spring 什么时候释放连接?

我问是因为我有一个方法可以进行同步 HTTP 调用以及对 Spring Repository 方法的调用。当我调用的服务由于超时而失败时,我开始在我们的日志中看到以下内容:

PoolExhaustedException:[http-nio-8080-exec-47] 超时:池为空。无法在 30 秒内获取连接,无可用 [size:15;忙:15;空闲:0;最后等待:30000]。

我假设这是由于在方法完成之前连接没有被释放回池,但我无法找到说明连接管理机制的文档。

【问题讨论】:

    标签: spring spring-data


    【解决方案1】:

    默认情况下,事务完成时连接会关闭,至少在您使用声明性事务并让 Spring 自己管理它们的情况下是这样。在the docs 中,有一个声明式事务实现的示例:

    public final class Boot {
    
        public static void main(final String[] args) throws Exception {
            ApplicationContext ctx = new ClassPathXmlApplicationContext("context.xml", Boot.class);
            FooService fooService = (FooService) ctx.getBean("fooService");
            fooService.insertFoo (new Foo());
        }
    }
    

    这就是你得到的输出:

    <!-- the Spring container is starting up... -->
    [AspectJInvocationContextExposingAdvisorAutoProxyCreator] - Creating implicit proxy for bean 'fooService' with 0 common interceptors and 1 specific interceptors
    
    <!-- the DefaultFooService is actually proxied -->
    [JdkDynamicAopProxy] - Creating JDK dynamic proxy for [x.y.service.DefaultFooService]
    
    <!-- ... the insertFoo(..) method is now being invoked on the proxy -->
    [TransactionInterceptor] - Getting transaction for x.y.service.FooService.insertFoo
    
    <!-- the transactional advice kicks in here... -->
    [DataSourceTransactionManager] - Creating new transaction with name [x.y.service.FooService.insertFoo]
    [DataSourceTransactionManager] - Acquired Connection [org.apache.commons.dbcp.PoolableConnection@a53de4] for JDBC transaction
    
    <!-- the insertFoo(..) method from DefaultFooService throws an exception... -->
    [RuleBasedTransactionAttribute] - Applying rules to determine whether transaction should rollback on java.lang.UnsupportedOperationException
    [TransactionInterceptor] - Invoking rollback for transaction on x.y.service.FooService.insertFoo due to throwable [java.lang.UnsupportedOperationException]
    
    <!-- and the transaction is rolled back (by default, RuntimeException instances cause rollback) -->
    [DataSourceTransactionManager] - Rolling back JDBC transaction on Connection [org.apache.commons.dbcp.PoolableConnection@a53de4]
    [DataSourceTransactionManager] - Releasing JDBC Connection after transaction
    [DataSourceUtils] - Returning JDBC Connection to DataSource
    
    Exception in thread "main" java.lang.UnsupportedOperationException at x.y.service.DefaultFooService.insertFoo(DefaultFooService.java:14)
    <!-- AOP infrastructure stack trace elements removed for clarity -->
    at $Proxy0.insertFoo(Unknown Source)
    at Boot.main(Boot.java:11)
    

    看来释放连接的方法是DataSourceUtils#releaseConnection。如果你想知道连接发生了什么,你至少应该为这个类启用日志记录。

    另一方面,我认为这是预期的行为。您有一个长时间运行的方法,该方法以事务方式执行,因此在失败时可以回滚,但您的代码每次执行时都会获取连接。为了解决您的问题,您可以尝试为您的方法优化代码根本不使其具有事务性,或者您可以增加最大连接量 用于您的连接池。

    【讨论】:

      【解决方案2】:

      我遇到了完全相同的问题。我试图释放与 DataSourceUtils#releaseConnection 的连接,但它似乎连接并没有在连接池中结束,因为连接持有者是容器而不是“我”

      我使用 wsa 的解决方案只是增加 yml 文件中的 maxPoolSize 并将 http 请求缓存在控制器中,但仍然希望能够释放连接...

      【讨论】:

        猜你喜欢
        • 2019-02-04
        • 1970-01-01
        • 1970-01-01
        • 2011-10-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-01-21
        • 2016-12-02
        相关资源
        最近更新 更多