Spring JDBC连接池的最佳实践

时间:2011-02-25 12:25:33

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

我有一个基本的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池库。

我应该避免使用任何图书馆吗?

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

你想分享的任何“战争故事”?

4 个答案:

答案 0 :(得分:21)

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

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

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

答案 1 :(得分:17)

作为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

答案 2 :(得分:9)

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

<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

答案 3 :(得分:0)

一定可以使用C3P0,它是为企业解决方案开发的。要检查优势,您可以follow this answer

以下是集成示例代码:

function PostData(){

    var validation=false;
    jQuery("#training_submit").prop('disabled', true);

    jQuery('#error_traff').hide();
    jQuery('#error_epost').hide();
    jQuery('#error_fname').hide();
    jQuery('#error_lname').hide();
    jQuery('#error_skola').hide();
    jQuery('#error_grade').hide();
    jQuery('#error_municipality').hide(); 

    var traff= jQuery("#training_traff").val().trim();
    var email= jQuery("#training_epost").val().trim();
    var firstname=jQuery("#training_fname").val().trim();
    var lastname= jQuery("#training_lname").val().trim();
    var phone= jQuery("#training_phone").val().trim();
    var school= jQuery("#training_skola").val().trim();
    var municipality = jQuery("#training_municipality").val().trim();
    var grade= jQuery("#training_grade").val().trim();
    var other= jQuery("#training_other").val().trim();

    if(traff =="") {
        jQuery('#error_traff').show();
        jQuery("#training_traff").focus(); 
    } else if(email =="") {
        jQuery('#error_epost').show();
        jQuery("#training_epost").focus(); 
    } else if(firstname =="") {
        jQuery('#error_fname').show();
        jQuery("#training_fname").focus();
    } else if(lastname =="") {
        jQuery('#error_lname').show();
        jQuery("#training_lname").focus();
    } else if(school =="") {
        jQuery('#error_skola').show();
        jQuery("#training_skola").focus();
    } else if(municipality =="") {
        jQuery('#error_municipality').show();
        jQuery("#training_municipality").focus();  
    } else if(grade =="") {
        jQuery('#error_grade').show();
        jQuery("#training_grade").focus();
    } else{
        jQuery('#loading').show();
        validation=true;
    }

    if(validation==true)
    {
        var user = {
        person_eMail: email,
        person_firstName:firstname,
        person_lastName: lastname,
        company_name: school,
        company_municipality:municipality,
        person_schoolYear: grade,
        person_position: "",
        project_name: "",
        Place: "",
        DeliveryLocation: "",
        person_phone: phone,
        Title: "",
        ReqDelivery: "",
        MeetingName: traff,
        OtherInfo: other,
        PreSchool: false,
        Elementary_Fk6: false,
        FK9: false,
        HighSchool_Other: false,
        Peephole: false,
            FormName:"Pedagogträffsintresse",
            RegisterDate: ""

        };

        jQuery.ajax({
            type: "POST",
            data: user,
            url: 'https://example.com/xxxx/xxx/',
            dataType: 'text',
            async: false,
            headers: {'Authorization': 'xxxxx'},
            success: function (result) {
                clearData(); 
                jQuery('#loading').hide();
                jQuery('#training_success').show();
                console.log(result);
            },
            error: function(error) {
                console.log(error);
                $("#training_submit").prop('disabled', false);
            }
        });        
    } else {
        jQuery("#training_submit").prop('disabled', false);
    }
}

此Bean用于获取@Bean public JpaTransactionManager transactionManager() { JpaTransactionManager transactionManager = new JpaTransactionManager(); transactionManager.setEntityManagerFactory(entityManagerFactory().getObject()); return transactionManager; }

JpaTransactionManager

此Bean用于获取@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; } 。它包含LocalContainerEntityManagerFactoryBeanDataSource,实体包名称PersistenceProviderClassPackagesToScan中的JpaProperties。

hibProperties()

在这里@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; } 并接受许多更重要的参数,例如maxPoolSize,MinPoolSize,MaxIdleSize等。 以下给出了环境参数:

ComboPooledDataSource

以下是完整的工作示例代码:

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

另一件事。这是gradle链接

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;
    }
}

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