Лучшие практики пула соединений Spring JDBC

У меня есть базовое приложение 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: C3P0 и DBCP. Поскольку я использую Oracle, я также могу использовать источник данных в пуле, предлагаемый Водитель.

Я понимаю, что доступно больше библиотек - например, новые библиотеки пула Apache Tomcat 7.

Есть ли какая-нибудь библиотека, которой мне действительно следует избегать?

Есть ли какая-либо рекомендуемая конфигурация, которую я должен использовать с данной библиотекой?

Хотите рассказать какую-нибудь «военную историю»?


person Luciano Fiandesio    schedule 25.02.2011    source источник


Ответы (4)


Разработка C3PO и DBCP застопорилась в основном из-за того, что они созрели. Я видел, что оба этих драйвера могут поддерживать сотни транзакций в секунду.

Пул Tomcat - это переработанный и обновленный драйвер DBCP. MyBatis 3.0 также содержит собственную реализацию пула, которая, судя по проверке кода, кажется надежной. Наконец, есть BoneCP, который утверждает, что имеет лучшую производительность. Я еще не использовал ничего из этого в проекте.

Наверное, лучший совет - выбрать любого из них и протестировать. Spring позволяет легко поменять местами позже.

person AngerClown    schedule 25.02.2011
comment
BoneCP больше не активен. Вы также можете взглянуть на HikariCP, который представляет собой пул фиксированных соединений и имеет большие преимущества в производительности. HikariCP для своей веб-страницы. - person muruga; 25.04.2016

В качестве альтернативы 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, похоже, официально устарел в пользу этого пула. Однако некоторые пользователи сообщали об ошибках при его использовании, так что это может быть слишком рано. Я могу использовать последние версии драйверов JDBC Oracle, поэтому я попробую и обновлю их здесь, как только у меня появится какая-либо информация по этому поводу.

Дополнительная информация в этой теме SO: Oracle UCP

person quantum    schedule 23.04.2011

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

Для правильной демонстрации вы можете использовать эту ссылку

person Bhargav Modi    schedule 12.12.2014
comment
Спасибо, что ответили на этот вопрос, это помогает снять нагрузку с нас, разработчиков HikariCP. - person brettw; 12.12.2014
comment
добро пожаловать @brettw, если он вам поможет, вы можете проголосовать за него :) - person Bhargav Modi; 12.12.2014
comment
Спасибо за внимание HiKaRi!, Небольшое обновление hikariConfig. Не знаю, как отформатировать комментарий: ‹bean id = hikariConfig class = com.zaxxer.hikari.HikariConfig› ‹имя свойства = значение maximumPoolSize = 50 /› ‹имя свойства = значение driverClassName = $ {db.driver} /› ‹Имя свойства = значение jdbcUrl = $ {db.url} /› ‹имя свойства = значение имени пользователя = $ {db.username} /› ‹имя свойства = значение пароля = $ {db.password} /› ‹/bean› - person Ondrej Burkert; 15.06.2016

Определенно вы можете использовать C3P0, он разработан для корпоративного решения. Чтобы проверить преимущества, вы можете следовать этому ответу.

Вот пример кода интеграции:

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

Этот компонент предназначен для получения 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;
}

Этот компонент предназначен для получения LocalContainerEntityManagerFactoryBean. Он принимает DataSource, PersistenceProviderClass, имя пакета сущности PackagesToScan и 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;
    }

Он использует 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;
    }
}

Другое дело. Вот ссылка на Gradle

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

Надеюсь, что это поможет вам. Спасибо :)

person Md. Sajedul Karim    schedule 14.08.2018