【问题标题】:Spring JDBC connection pool best practicesSpring JDBC 连接池最佳实践
【发布时间】:2011-07-04 06:48:02
【问题描述】:

我有一个基本的 Spring JDBC 应用程序,它具有非常基本的配置:

<bean id="myDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
   <property name="driverClassName" value="oracle.jdbc.OracleDriver"/>
   <property name="url" value="jdbc:oracle:thin:@1.1.1.1:1521:XXX"/>
   <property name="username" value="username"/>
   <property name="password" value="password"/>
</bean>

<bean id="dbThing" class="com.DbThing">
   <property name="dataSource" ref="myDataSource"/>
</bean>

我想介绍一个连接池,在阅读了SO上的几个线程后,我对使用哪个池库有点困惑。

似乎在 SO 上有更多学分的库是 C3P0DBCP。由于我使用的是Oracle,所以我也可以使用驱动提供的pooled data source

我知道还有更多可用的库 - 例如新的 Apache Tomcat 7 池化库。

有没有我真的应该避免的图书馆?

对于给定的库,我应该使用任何推荐的配置吗?

您想分享任何“战争故事”吗?

【问题讨论】:

    标签: java spring connection-pooling c3p0 apache-commons-dbcp


    【解决方案1】:

    C3PO 和 DBCP 发展停滞主要是因为它们已经成熟。我已经看到这两个驱动程序都能够支持每秒数百个事务。

    Tomcat 池是经过重新设计和更新的 DBCP 驱动程序。 MyBatis 3.0 还包含它自己的池化实现,基于代码检查,它看起来很可靠。最后是BoneCP,它声称有最好的性能。我还没有在项目中使用过这些。

    可能最好的建议是选择其中任何一个进行测试。 Spring 使以后可以轻松更换。

    【讨论】:

    • BoneCP 不再处于活动状态。您还可以查看 HikariCP,它是一个固定连接池,具有很大的性能优势。 HikariCP 为他们的网页。
    【解决方案2】:

    作为 BoneCP 的替代方案,您是否尝试过 Oracle 自己的数据库连接池?

    过去几周我有很好的经验,所以值得一试 - 另外,我想 Oracle 会知道关于创建连接池的一两件事,尤其是在与他们自己的数据库配对时.

    <bean id="dataSource" class="oracle.jdbc.pool.OracleConnectionPoolDataSource">
        <property name="URL" value="${jdbc.url}" />
        <property name="user" value="${jdbc.username}" />
        <property name="password" value="${jdbc.password}" />
    </bean>
    

    更新:另外,如果您正在使用(其中一个)最新的 Oracle JDBC 驱动程序 (11.2.0.1+),您可能想尝试新的通用连接池。 OracleConnectionPoolDataSource 似乎已正式弃用以支持此池。但是,一些用户报告了使用它的错误,因此可能为时过早。我可以使用 Oracle 最新的 JDBC 驱动程序,所以我会尝试一下,一旦有任何相关信息,我会在这里更新。

    有关此 SO 线程的更多信息:Oracle UCP

    【讨论】:

      【解决方案3】:

      BoneCP 一直声称,但随后引入了一个名为HiKariCP 的新工具,它克服了传递工具中存在的许多缺点,您可以通过在application-context.xml 中进行以下更改来配置它

      <bean id="hikariConfig" class="com.zaxxer.hikari.HikariConfig">
        <property name="maximumPoolSize" value="10" />
        <property name="minimumPoolSize" value="2" />
        <property name="dataSourceClassName" 
                  value="oracle.jdbc.pool.OracleDataSource" />
        <property name="dataSourceProperties" ref="props" />
        <property name="poolName" value="springHikariCP" />
      </bean>
      
      <bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource">
            <constructor-arg ref="hikariConfig" />
      </bean>
      
      <util:properties id="props" location="classpath:datasource.properties"/>
      

      database.properties 中,您应该提供数据库的详细信息,如下所示

       url=jdbc:oracle:thin:@IP:port:SID/Databasename
       user=usernmae
       password=password
      

      对于正确的演示,您可以使用this link

      【讨论】:

      • 感谢您回答这个问题,这有助于减轻我们 HikariCP 开发人员的负担。
      • 欢迎@brettw,如果它对您有帮助,您可以投票:)
      • 感谢 HiKaRi 的指出!hikariConfig 的一个小更新。不知道如何格式化评论:
      【解决方案4】:

      你当然可以使用 C3P0,这是为企业解决方案开发的。要查看优势,您可以follow this answer

      以下是集成示例代码:

      @Bean
          public JpaTransactionManager transactionManager() {
              JpaTransactionManager transactionManager =
                      new JpaTransactionManager();
              transactionManager.setEntityManagerFactory(entityManagerFactory().getObject());
              return transactionManager;
          }
      

      此 Bean 用于获取 JpaTransactionManager

      @Primary
      @Bean
      public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
      
          LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
          entityManagerFactoryBean.setDataSource(dataSource());
          entityManagerFactoryBean.setPersistenceProviderClass(HibernatePersistenceProvider.class);
          entityManagerFactoryBean.setPackagesToScan("YOUR.DATABSE.ENTITY.PACKAGE");
          entityManagerFactoryBean.setJpaProperties(hibProperties());
      
          return entityManagerFactoryBean;
      }
      

      此 Bean 用于获取 LocalContainerEntityManagerFactoryBean。它需要 DataSourcePersistenceProviderClass ,实体包名称 PackagesToScan 和来自 hibProperties() 的 JpaProperties。

      @Bean
          public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
              return new PersistenceExceptionTranslationPostProcessor();
          }
      
      private Properties hibProperties() {
              Properties properties = new Properties();
              properties.put("hibernate.dialect", env.getProperty("hibernate.dialect"));
              properties.put("hibernate.show_sql", env.getProperty("hibernate.show_sql"));
              properties.put("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto"));
              return properties;
          }
      

      这里,env value are comming from application.properties

      检查以下属性:

      hibernate.dialect: org.hibernate.dialect.Oracle12cDialect
      hibernate.show_sql: false
      hibernate.hbm2ddl.auto: none
      

      主要部分是数据源设置。这是在下面给出的

      @Bean
          public ComboPooledDataSource dataSource(){
              ComboPooledDataSource dataSource = new ComboPooledDataSource();
      
              try {
                  dataSource.setDriverClass(env.getProperty("db.driver"));
                  dataSource.setJdbcUrl(env.getProperty("db.url"));
                  dataSource.setUser(env.getProperty("db.username"));
                  dataSource.setPassword(env.getProperty("db.password"));
                  dataSource.setMinPoolSize(Integer.parseInt(env.getProperty("minPoolSize")));
                  dataSource.setMaxPoolSize(Integer.parseInt(env.getProperty("maxPoolSize")));
                  dataSource.setMaxIdleTime(Integer.parseInt(env.getProperty("maxIdleTime")));
                  dataSource.setMaxStatements(Integer.parseInt(env.getProperty("maxStatements")));
                  dataSource.setMaxStatementsPerConnection(Integer.parseInt(env.getProperty("maxStatementsPerConnection")));
                  dataSource.setMaxIdleTimeExcessConnections(10000);
      
              } catch (PropertyVetoException e) {
                  e.printStackTrace();
              }
              return dataSource;
          }
      

      它使用了ComboPooledDataSource,它采用了许多更重要的参数,如 maxPoolSize、MinPoolSize、MaxIdleSize 等。 环境参数如下:

      db.driver: oracle.jdbc.driver.OracleDriver // for Oracle
      db.username: YOUR_USER_NAME
      db.password: YOUR_USER_PASSWORD
      db.url: DATABASE_URL
      minPoolSize:5 // number of minimum poolSize
      maxPoolSize:100 // number of maximum poolSize
      maxIdleTime:5 // In seconds. After that time it will realease the unused connection.
      maxStatements:1000
      maxStatementsPerConnection:100
      maxIdleTimeExcessConnections:10000
      

      这是完整的工作示例代码:

      import com.mchange.v2.c3p0.ComboPooledDataSource;
      import org.hibernate.jpa.HibernatePersistenceProvider;
      import org.springframework.beans.factory.annotation.Autowired;
      import org.springframework.beans.factory.annotation.Qualifier;
      import org.springframework.context.annotation.*;
      import org.springframework.core.env.Environment;
      import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor;
      import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
      import org.springframework.orm.jpa.JpaTransactionManager;
      import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
      import org.springframework.transaction.annotation.EnableTransactionManagement;
      
      import javax.sql.DataSource;
      import java.beans.PropertyVetoException;
      import java.util.Properties;
      
      @Configuration
      @EnableTransactionManagement
      @EnableJpaRepositories
      @PropertySource("classpath:application.properties")
      @Scope("singleton")
      public class TestDataSource {
      
          @Autowired
          private Environment env;
      
          @Qualifier("dataSource")
          @Autowired
          private DataSource dataSource;
      
          @Bean
          public JpaTransactionManager transactionManager() {
              JpaTransactionManager transactionManager =
                      new JpaTransactionManager();
              transactionManager.setEntityManagerFactory(entityManagerFactory().getObject());
              return transactionManager;
          }
      
          @Primary
          @Bean
          public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
      
              LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
              entityManagerFactoryBean.setDataSource(dataSource());
              entityManagerFactoryBean.setPersistenceProviderClass(HibernatePersistenceProvider.class);
              entityManagerFactoryBean.setPackagesToScan("YOUR.PACKAGE.NAME");
              entityManagerFactoryBean.setJpaProperties(hibProperties());
      
              return entityManagerFactoryBean;
          }
      
          @Bean
          public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
              return new PersistenceExceptionTranslationPostProcessor();
          }
      
          @Bean
          public ComboPooledDataSource dataSource(){
              ComboPooledDataSource dataSource = new ComboPooledDataSource();
      
              try {
                  dataSource.setDriverClass(env.getProperty("db.driver"));
                  dataSource.setJdbcUrl(env.getProperty("db.url"));
                  dataSource.setUser(env.getProperty("db.username"));
                  dataSource.setPassword(env.getProperty("db.password"));
                  dataSource.setMinPoolSize(Integer.parseInt(env.getProperty("minPoolSize")));
                  dataSource.setMaxPoolSize(Integer.parseInt(env.getProperty("maxPoolSize")));
                  dataSource.setMaxIdleTime(Integer.parseInt(env.getProperty("maxIdleTime")));
                  dataSource.setMaxStatements(Integer.parseInt(env.getProperty("maxStatements")));
                  dataSource.setMaxStatementsPerConnection(Integer.parseInt(env.getProperty("maxStatementsPerConnection")));
                  dataSource.setMaxIdleTimeExcessConnections(10000);
      
              } catch (PropertyVetoException e) {
                  e.printStackTrace();
              }
              return dataSource;
          }
      
          private Properties hibProperties() {
              Properties properties = new Properties();
              properties.put("hibernate.dialect", env.getProperty("hibernate.dialect"));
              properties.put("hibernate.show_sql", env.getProperty("hibernate.show_sql"));
              properties.put("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto"));
              return properties;
          }
      }
      

      另外的事情。这是毕业链接

      compile group: 'org.hibernate', name: 'hibernate-c3p0', version: '5.2.10.Final'
      

      希望这会对您有所帮助。 谢谢:)

      【讨论】:

        猜你喜欢
        • 2011-01-19
        • 2015-03-25
        • 1970-01-01
        • 1970-01-01
        • 2015-08-03
        • 2012-10-10
        • 2022-07-08
        相关资源
        最近更新 更多