2016-11-18 46 views
0

我们正在尝试使用c3p0实现连接池。问题是当我们的服务器上没有很长时间的事务时,第一个下一个事务就会有连接超时问题。春季JPA与c3p0在第一次请求时有连接超时

异常堆栈跟踪:

 Could not open JPA EntityManager for transaction; nested exception is javax.persistence.Pers 
       istenceException: org.hibernate.TransactionException: JDBC begin transaction failed: 
       org.springframework.transaction.CannotCreateTransactionException: Could not open JPA EntityManager for transacti 
       on; nested exception is javax.persistence.PersistenceException: org.hibernate.TransactionException: JDBC begin t 
       ransaction failed: 
         at org.springframework.orm.jpa.JpaTransactionManager.doBegin(JpaTransactionManager.java:431) 
         at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPla 
       tformTransactionManager.java:373) 
         at org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(Tra 
       nsactionAspectSupport.java:427) 
         at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(Transact 
       ionAspectSupport.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.$Proxy559.getMerchantById(Unknown Source) 
         at com.ag.controller.MerchantController.getMerchantById(MerchantController.java:1111) 
         at com.ag.controller.MerchantController.checkoutMerchant(MerchantController.java:226) 
         at sun.reflect.GeneratedMethodAccessor1766.invoke(Unknown Source) 
         at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
         at java.lang.reflect.Method.invoke(Method.java:498) 
         at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:22 
       1) 
         at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod 
       .java:137) 
         at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(S 
       ervletInvocableHandlerMethod.java:111) 
         at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMetho 
       d(RequestMappingHandlerAdapter.java:806) 
         at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(Req 
       uestMappingHandlerAdapter.java:729) 
         at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodA 
       dapter.java:85) 
         at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959) 
         at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893) 
         at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970) 
         at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872) 
         at javax.servlet.http.HttpServlet.service(HttpServlet.java:648) 
         at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846) 
         at javax.servlet.http.HttpServlet.service(HttpServlet.java:729) 
         at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:292) 
         at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207) 
         at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java: 
       85) 
         at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
         at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240) 
         at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207) 
         at com.ag.configuration.XSSFilter.doFilter(XSSFilter.java:27) 
         at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240) 
         at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207) 
         at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) 
         at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240) 
         at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207) 
         at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:212) 
         at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106) 
         at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502) 
         at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:141) 
         at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79) 
         at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:616) 
         at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88) 
         at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:522) 
         at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1095) 
         at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:672) 
         at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1500) 
         at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1456) 
         at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) 
         at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) 
         at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) 
         at java.lang.Thread.run(Thread.java:745) 
       Caused by: javax.persistence.PersistenceException: org.hibernate.TransactionException: JDBC begin transaction fa 
       iled: 
         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.j 
       ava:1771) 
         at org.hibernate.jpa.internal.TransactionImpl.begin(TransactionImpl.java:64) 
         at org.springframework.orm.jpa.vendor.HibernateJpaDialect.beginTransaction(HibernateJpaDialect.java:166) 
         at org.springframework.orm.jpa.JpaTransactionManager.doBegin(JpaTransactionManager.java:380) 
         ... 53 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) 
         ... 55 more 
       Caused by: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: The last packet successfully received from t 
       he server was 54,078,423 milliseconds ago. The last packet sent successfully to the server was 54,078,423 milli 
       seconds ago. is longer than the server configured value of 'wait_timeout'. You should consider either expiring a 
       nd/or testing connection validity before use in your application, increasing the server configured values for cl 
       ient timeouts, or using the Connector/J connection property 'autoReconnect=true' to avoid this problem. 
         at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) 
         at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) 
         at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) 
         at java.lang.reflect.Constructor.newInstance(Constructor.java:423) 
         at com.mysql.jdbc.Util.handleNewInstance(Util.java:400) 
         at com.mysql.jdbc.SQLError.createCommunicationsException(SQLError.java:1038) 
         at com.mysql.jdbc.MysqlIO.send(MysqlIO.java:3621) 
         at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2429) 
         at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2594) 
         at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2541) 
         at com.mysql.jdbc.ConnectionImpl.setAutoCommit(ConnectionImpl.java:4882) 
         at com.mchange.v2.c3p0.impl.NewProxyConnection.setAutoCommit(NewProxyConnection.java:912) 
         at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.doBegin(JdbcTransaction.java:72) 
         ... 58 more 
       Caused by: java.net.SocketException: Connection timed out 
         at java.net.SocketOutputStream.socketWrite0(Native Method) 
         at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:109) 
         at java.net.SocketOutputStream.write(SocketOutputStream.java:153) 
         at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:82) 
         at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:140) 
         at com.mysql.jdbc.MysqlIO.send(MysqlIO.java:3603) 
         ... 64 more 

数据源配置:

 @Primary 
     @Bean 
     public DataSource agDataSource() { 

     ComboPooledDataSource dataSource = new ComboPooledDataSource(); 
      try { 
       dataSource.setDriverClass(Preconditions.checkNotNull(environment.getRequiredProperty("hibernate.connection.driver_class"))); 
      } catch (IllegalStateException | PropertyVetoException e) { 
       e.printStackTrace(); 
      } 
      dataSource.setJdbcUrl(Preconditions.checkNotNull(environment.getRequiredProperty("hibernate.connection.url"))); 
      dataSource.setUser(Preconditions.checkNotNull(environment.getRequiredProperty("hibernate.connection.username"))); 
      dataSource.setPassword(Preconditions.checkNotNull("hibernate.connection.password")); 
     } 



     @Primary 
     @Bean(name="agEntityManagerFactory") 
     public LocalContainerEntityManagerFactoryBean agEntityManagerFactory() throws ClassNotFoundException { 
      final LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean(); 

      entityManagerFactoryBean.setDataSource(agDataSource()); 
      entityManagerFactoryBean.setPackagesToScan(new String[] { "com.ag.entities" }); 
      entityManagerFactoryBean.setPersistenceProviderClass(HibernatePersistenceProvider.class); 

      final HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); 
      vendorAdapter.setShowSql(true); 
      entityManagerFactoryBean.setJpaVendorAdapter(vendorAdapter); 
      //entityManagerFactoryBean.setJpaVendorAdapter(vendorAdapter); 
      entityManagerFactoryBean.setJpaProperties(hibernateProperties()); 

      entityManagerFactoryBean.afterPropertiesSet(); 
      entityManagerFactoryBean.setLoadTimeWeaver(new InstrumentationLoadTimeWeaver()); 

      return entityManagerFactoryBean; 
     } 

     @Primary 
     @Bean(name = "agTransactionManager") 
     public PlatformTransactionManager agTransactionManager() { 
      final JpaTransactionManager transactionManager = new JpaTransactionManager(); 
      try { 
       transactionManager.setEntityManagerFactory(agEntityManagerFactory().getObject()); 
       transactionManager.setDataSource(agDataSource()); 
       transactionManager.setJpaDialect(new HibernateJpaDialect()); 
       //transactionManager.setNestedTransactionAllowed(true); 
      } catch (ClassNotFoundException e) { 
       e.printStackTrace(); 
      } 
      return transactionManager; 
     } 
+0

在空闲时配置连接检查(有关更多信息,请参阅http://stackoverflow.com/questions/30451470/connection-to-db-dies-after-424-in-spring-boot-jpa-hibernate/30455408#30455408)信息,这是春季启动,但给你一个什么配置的概述)。我还建议使用另一个连接池,如HikariCP而不是C3P0。你也知道你的'Preconditions.checkNotNull'是多余的?这是使用'getRequiredProperty'的关键。你也不应该在代码中调用'afterPropertiesSet'。春天会为你做到这一点。 –

+0

@ M.Deinum感谢您的建议。我一定会在我的代码中进行更正。我可以通过设置mysql连接的一些连接属性来在开发机器上复制相同的问题。 –

回答

2

我能够通过设置数据源对象本身的连接池属性来解决问题。我认为休眠属性不能反映池设置。我可以通过在mysql的my.ini文件中设置wait_timeout = 60,interactive_timeout = 60(即1分钟)来复制该问题。然后服务器启动后我尝试了第一个事务,等了1分钟,然后尝试了失败的txn。然后我启用查询日志(通过设置在my.ini的两个属性:

general_log = 1个

general_log_file = “C:/xampp/mysql/data/mysql.log”

我上面的设置启用,检查是否得到执行我选择1个验证查询或not.I试过池设置在数据源对象本身就开始工作。查询日志也显示选择素1执行每休眠。 c3p0.idle_tes t_period秒。

@Primary 
     @Bean 
     public DataSource agDataSource() { 

     ComboPooledDataSource dataSource = new ComboPooledDataSource(); 
      try { 
       dataSource.setDriverClass(environment.getRequiredProperty("hibernate.connection.driver_class")); 
      } catch (IllegalStateException | PropertyVetoException e) { 
       e.printStackTrace(); 
      } 
      dataSource.setJdbcUrl(environment.getRequiredProperty("hibernate.connection.url")); 
      dataSource.setUser(environment.getRequiredProperty("hibernate.connection.username")); 
      dataSource.setPassword(environment.getRequiredProperty("hibernate.connection.password")); 

      dataSource.setMaxPoolSize(Integer.parseInt(environment.getRequiredProperty("hibernate.c3p0.max_size"))); 
      dataSource.setMinPoolSize(Integer.parseInt(environment.getRequiredProperty("hibernate.c3p0.min_size"))); 
      dataSource.setMaxIdleTime(Integer.parseInt(environment.getRequiredProperty("hibernate.c3p0.timeout"))); 
      dataSource.setMaxStatements(Integer.parseInt(environment.getRequiredProperty("hibernate.c3p0.max_statements"))); 
      dataSource.setIdleConnectionTestPeriod(Integer.parseInt(environment.getRequiredProperty("hibernate.c3p0.idle_test_period"))); 
      dataSource.setAcquireIncrement(Integer.parseInt(environment.getRequiredProperty("hibernate.c3p0.acquire_increment"))); 
      dataSource.setPreferredTestQuery(environment.getRequiredProperty("hibernate.c3p0.preferredTestQuery")); 
      dataSource.setTestConnectionOnCheckin(true); 
      dataSource.setTestConnectionOnCheckout(true); 

      return dataSource; 
     } 

现在它工作正常。快乐。我发布了答案和我所做的验证我的设置的步骤,以便它可以帮助其他人。