2016-08-27 3 views
1

Если я вызываю метод Spring Repository для запроса БД, когда весна освобождает соединение?Spring Data DB Connection Management

Я спрашиваю, потому что у меня есть метод, который делает синхронный HTTP-вызов вместе с вызовом метода Spring Repository. Когда услуга я звонил, чтобы не удалось, из-за тайм-аута, я начал видеть следующее в наших журналах:

PoolExhaustedException: [HTTP-NiO-8080-Exec-47] Тайм-аут: бассейн пуст. Не удалось получить соединение за 30 секунд, недоступно [размер: 15; заняты: 15; холостой ход: 0; lastwait: 30000].

Я предполагаю, что это связано с тем, что соединение не было выпущено обратно в пул до тех пор, пока метод не будет завершен, но я не могу найти и документацию с указанием механики управления подключением.

ответ

0

По умолчанию соединение закрывается, когда транзакция завершается, по крайней мере, если вы используете декларативные транзакции и позволяете 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 [[email protected]] 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 [[email protected]] 
[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. Если вы хотите узнать, что происходит с подключениями, вы должны включить ведение журнала для этого класса как минимум.

С другой стороны, я думаю, что это ожидаемое поведение. У вас давно запущенный метод, который выполняется транзакционно, поэтому он может быть откат при сбое, но ваш код приобретает соединение каждый раз, когда вы его выполняете. Чтобы решить вашу проблему, вы можете попробовать оптимизировать код для вашего метода, не сделать его транзакционным вообще или вы могли бы увеличить максимальное количество подключений для вашего пула подключения.

0

У меня была такая же проблема. Я попытался освободить соединение с DataSourceUtils # releaseConnection, но он швы, что соединение не попало в пул соединений, потому что держатель подключения - это контейнер не «я»

Решение, с которым я пошел с wsa только для увеличьте maxPoolSize в файле yml и кешируйте http-запрос в контроллере, но все же хотите иметь возможность просто отпустить соединение ...