web-dev-qa-db-ja.com

Spring BootでPostgres接続が閉じられたエラー

REST api。 Postgres DB:これは完全なスタックトレースです。

org.springframework.transaction.CannotCreateTransactionException: Could not open JPA EntityManager for transaction; nested exception is javax.persistence.PersistenceException: org.hibernate.TransactionException: JDBC begin transaction failed: 
    at org.springframework.orm.jpa.JpaTransactionManager.doBegin(JpaTransactionManager.Java:431)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.Java:373)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.Java:457)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.Java:276)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.Java:96)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.Java:179)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.Java:207)
    at com.Sun.proxy.$Proxy91.findByUriMoniker(Unknown Source)
    at com.mypkg.businessobjects.OrderInfoBO.getOrderInfo(OrderInfoBO.Java:76)
    at com.mypkg.controller.OrderInfoController.getOrderInfo(OrderInfoController.Java:78)
    at Sun.reflect.GeneratedMethodAccessor104.invoke(Unknown Source)
    at Sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.Java:43)
    at Java.lang.reflect.Method.invoke(Method.Java:483)
    at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.Java:221)
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.Java:137)
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.Java:110)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.Java:777)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.Java:706)
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.Java:85)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.Java:943)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.Java:877)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.Java:966)
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.Java:857)
    at javax.servlet.http.HttpServlet.service(HttpServlet.Java:687)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.Java:842)
    at javax.servlet.http.HttpServlet.service(HttpServlet.Java:790)
    at io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.Java:85)
    at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.Java:130)
    at com.mypkg.config.CORSFilter.doFilter(CORSFilter.Java:39)
    at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.Java:60)
    at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.Java:132)
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.Java:88)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.Java:107)
    at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.Java:60)
    at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.Java:132)
    at io.undertow.servlet.handlers.FilterHandler.handleRequest(FilterHandler.Java:85)
    at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.Java:61)
    at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.Java:36)
    at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.Java:131)
    at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.Java:56)
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.Java:43)
    at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.Java:45)
    at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.Java:63)
    at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.Java:58)
    at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.Java:70)
    at io.undertow.security.handlers.SecurityInitialHandler.handleRequest(SecurityInitialHandler.Java:76)
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.Java:43)
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.Java:43)
    at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.Java:261)
    at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.Java:247)
    at io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.Java:76)
    at io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.Java:166)
    at io.undertow.server.Connectors.executeRootHandler(Connectors.Java:197)
    at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.Java:759)
    at Java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.Java:1142)
    at Java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.Java:617)
    at Java.lang.Thread.run(Thread.Java:745)
Caused by: javax.persistence.PersistenceException: org.hibernate.TransactionException: JDBC begin transaction failed: 
    at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.Java:1763)
    at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.Java:1677)
    at org.hibernate.jpa.spi.AbstractEntityManagerImpl.throwPersistenceException(AbstractEntityManagerImpl.Java:1771)
    at org.hibernate.jpa.internal.TransactionImpl.begin(TransactionImpl.Java:64)
    at org.springframework.orm.jpa.vendor.HibernateJpaDialect.beginTransaction(HibernateJpaDialect.Java:159)
    at org.springframework.orm.jpa.JpaTransactionManager.doBegin(JpaTransactionManager.Java:380)
    ... 56 more
Caused by: org.hibernate.TransactionException: JDBC begin transaction failed: 
    at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.doBegin(JdbcTransaction.Java:76)
    at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.begin(AbstractTransactionImpl.Java:162)
    at org.hibernate.internal.SessionImpl.beginTransaction(SessionImpl.Java:1435)
    at org.hibernate.jpa.internal.TransactionImpl.begin(TransactionImpl.Java:61)
    ... 58 more
Caused by: org.postgresql.util.PSQLException: This connection has been closed.
    at org.postgresql.jdbc2.AbstractJdbc2Connection.checkClosed(AbstractJdbc2Connection.Java:833)
    at org.postgresql.jdbc2.AbstractJdbc2Connection.getAutoCommit(AbstractJdbc2Connection.Java:794)
    at Sun.reflect.GeneratedMethodAccessor35.invoke(Unknown Source)
    at Sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.Java:43)
    at Java.lang.reflect.Method.invoke(Method.Java:483)
    at org.Apache.Tomcat.jdbc.pool.ProxyConnection.invoke(ProxyConnection.Java:126)
    at org.Apache.Tomcat.jdbc.pool.JdbcInterceptor.invoke(JdbcInterceptor.Java:108)
    at org.Apache.Tomcat.jdbc.pool.DisposableConnectionFacade.invoke(DisposableConnectionFacade.Java:81)
    at com.Sun.proxy.$Proxy56.getAutoCommit(Unknown Source)
    at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.doBegin(JdbcTransaction.Java:68)
    ... 61 more

アプリケーションを再起動すると消えます。 postgres DBを再起動すると、この問題が発生すると思います。なぜこうなった?

24
drunkenfist

非常に有効な質問であり、この問題は通常多くの人が直面しています。通常、例外は、プールとデータベースの間でネットワーク接続が失われたときに発生します(ほとんどの場合、再起動による)。指定したスタックトレースを見ると、jdbc poolを使用して接続を取得していることが明らかです。 JDBC poolには、さまざまな接続プール設定を微調整し、プール内で行われていることに関する詳細を記録するオプションがあります。

プール構成の詳細なApacheドキュメント を参照して、放棄タイムアウトを指定できます。

RemoveAbandoned、removeAbandonedTimeout、logAbandonedパラメーターを確認します

さらに、追加のプロパティを使用して、検証をさらに強化できます。

接続の有効性のためにtestXXXとvalidationQueryを使用します。

10
CuriousMind

これは、他の投稿で半ば答えられたようなものであり、非常に明確にしたかったのです。また、私はもっとスプリングブート風になりたかった。必要に応じて、時間間隔を自由に変更してください。

オプション1:破損した接続をプールから破棄します。

次のプロパティを使用します。

spring.datasource.test-on-borrow=true
spring.datasource.validation-query=SELECT 1;
spring.datasource.validation-interval=30000

オプション2:プール内の接続を維持します。

次のプロパティを使用します。

spring.datasource.test-while-idle=true
spring.datasource.validation-query=SELECT 1;
spring.datasource.time-between-eviction-runs-millis=60000

オプション3:アイドル接続を積極的に破棄します。

これらのプロパティを使用します(注:Spring Bootの信頼できるドキュメントを見つけることができませんでした。また、タイムアウトはミリ秒ではなく秒単位です)。

spring.datasource.remove-abandoned=true
spring.datasource.remove-abandoned-timeout=60

ハッピーブート!

27
James Watkins

私はまったく同じ問題を抱えていました このセットアップで 、また Tomcatのデータソース (_org.Apache.Tomcat.jdbc.pool_)を使用してHeroku Postgresに接続します:

_org.springframework.transaction.CannotCreateTransactionException: 
    Could not open JPA EntityManager for transaction
org.hibernate.TransactionException: JDBC begin transaction failed: ] 
    with root cause
org.postgresql.util.PSQLException: This connection has been closed.
_

私にとってそれを解決したのは、これをDataSourceの初期化コードに追加することでした( Grailsの質問 から借用しています):

_dataSource.setTestOnBorrow(true);
dataSource.setTestWhileIdle(true);
dataSource.setTestOnReturn(true);
dataSource.setValidationQuery("SELECT 1");
_

安定した接続を得るためにこれら3つすべてが必要かどうかはわかりませんが、おそらくそうではありませんが、すべてを有効にしても大した害はありません。

JavaDocsは何が起こっているかを明確にします。 setTestOnBorrow() 。おそらく、デフォルトではそのようなテストが行​​われないことに少し驚いています。

1
Jonik

私はまったく同じ問題を抱えていましたが、私の場合、前述の答えは役に立ちませんでした。長いクエリを実行すると、同じエラーが表示されることがわかりました。私の場合、findAll(Iterable ids)を呼び出し、100'000を超えるIDの膨大なリストを渡しました。リストをパーティション分割し(たとえば、Apache CommonsまたはGoogle GuavaのListUtilsを使用)、より少ないIDでfindAll()を呼び出すと、うまくいきました。

0
Tai Truong