Я использую спящий режим, чтобы попытаться получить кешированный запрос.

@Transactional
public interface ProductDAO extends JpaRepository<Product, Long> {
    @QueryHints({ @QueryHint(name = "org.hibernate.cacheable", value = "true") })
    Product findByCode(String code);
}

Я тестирую нагрузку и делаю это в большом цикле из 1000 итераций.

for (int i = 0; i < 500; i++) {
            URL myURL = new URL("http://localhost:8080/test");
            URLConnection myURLConnection = myURL.openConnection();
            myURLConnection.connect();
            myURLConnection.getContent();
        }

Я проверил с помощью showql и вижу, что при первом обращении к БД создается только 1 оператор SQL, после чего он кэшируется.

Тем не менее, я все еще получаю следующую ошибку, хотя SQL не отображается:

com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Too many connections

Мои свойства Hibernate:

#hibernate properties
hibernate.dialect = ${hibernate.dialect}
hibernate.show_sql = false
hibernate.hbm2ddl.auto = ${hibernate.hbm2ddl}
hibernate.c3p0.min_size = 10
hibernate.c3p0.max_size = 100
hibernate.c3p0.timeout = 300
hibernate.c3p0.max_statements = 50
hibernate.c3p0.acquire_increment = 5
hibernate.c3p0.idle_test_period = 3000

hibernate.cache.use_second_level_cache=true
hibernate.cache.region.factory_class=org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory
hibernate.cache.use_query_cache=true

Конфигурация базы данных:

<bean name="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="url" value="${db.url}" />
    <property name="driverClassName" value="${db.driverClassName}" />
    <property name="username" value="${db.username}" />
    <property name="password" value="${db.password}" />
</bean>

<bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" id="entityManagerFactory">
    <property name="dataSource" ref="dataSource" />

    <property name="jpaVendorAdapter">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
            <property name="showSql" value="false" />
            <property name="generateDdl" value="true" />
            <property name="databasePlatform" value="${hibernate.dialect}" />
        </bean>
    </property>

    <property name="jpaProperties" ref="hibernateProperties" />

    <property name="packagesToScan">
        <array>
            <value>com.exammple.model</value>
        </array>
    </property>
</bean>

<bean id="hibernateProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
    <property name="location" value="classpath:/spring/hibernate.properties" />
</bean>

<bean id="sessionFactory" factory-bean="entityManagerFactory" factory-method="getSessionFactory" />

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="dataSource" ref="dataSource" />
    <property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>

<tx:annotation-driven transaction-manager="transactionManager" />

<jpa:repositories base-package="com.example.dal" entity-manager-factory-ref="entityManagerFactory"
    transaction-manager-ref="transactionManager" repository-impl-postfix="CustomImpl" />
3
DD. 9 Мар 2015 в 20:46

2 ответа

Лучший ответ

Проблема в вашей конфигурации: вы не используете пул соединений.

Вы настраиваете DriverManagerDataSource, который не является правильным пулом соединений. Вы вводите этот компонент в LocalContainerEntityManagerFactoryBean, что делает ваши свойства hibernate.connection и hibernate.c3p0 бесполезными, они не используются.

Решение довольно простое: отбросьте свойства hibernate.c3p0 и hibernate.connection и замените DriverManagerDataSource правильной реализацией пула. Я бы порекомендовал HikariCP вместо C3P0, но это личное предпочтение.

<bean id="hikariConfig" class="com.zaxxer.hikari.HikariConfig">
    <property name="poolName" value="springHikariCP" />
    <property name="connectionTestQuery" value="SELECT 1" />
    <property name="dataSourceClassName" value="${db.driverClassName}" />
    <property name="dataSourceProperties">
        <props>
            <prop key="url">${db.url}</prop>
            <prop key="user">${db.username}</prop>
            <prop key="password">${jdb.password}</prop>
        </props>
    </property>
</bean>

<bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource" destroy-method="close">
    <constructor-arg ref="hikariConfig" />
</bean>
4
M. Deinum 10 Мар 2015 в 08:56

У этой проблемы может быть несколько проблем:

  1. Вы не закрываете соединения с базой данных.

  2. Вы устанавливаете максимальный пул соединений размер пула, который превышает максимально допустимое количество подключений ваш сервер базы данных. Когда количество клиентов превышает максимально допустимое количество подключений, возникает подобное исключение.

Я мог бы использовать FlexyPool, чтобы отслеживать использование пула соединений и выяснять, не протекают ли соединения или нет. сдаются в долгосрочную аренду.

Обновить

Как уже сказал М. Дейнум, вы не используете пул соединений.

Вы все еще можете использовать свойства Hibernate C3P0, но вам нужно удалить dataSource из LocalContainerEntityManagerFactoryBean:

<property name="dataSource" ref="dataSource" />

Таким образом, Hibernate может использовать свойства hibernate.c3p0.

0
Vlad Mihalcea 6 Янв 2018 в 09:49