Как я могу предотвратить создание Hibernate + c3p0 + MySql большого количества спящих соединений? - PullRequest
4 голосов
/ 22 сентября 2010

Я использую GWT с Hibernate, c3p0 и MySQL для создания веб-приложения с ограниченной аудиторией (максимум 50 пользователей в день). Во время тестирования я обнаружил, что Hibernate открывает соединение с каждым сеансом, но не закрывает его, независимо от использования метода close().

Моя текущая конфигурация следующая:

hibernate.connection.driver_class=com.mysql.jdbc.Driver
hibernate.connection.url=
hibernate.connection.username=
hibernate.connection.password=
hibernate.dialect=org.hibernate.dialect.MySQLDialect
hibernate.current_session_context_class=thread
hibernate.c3p0.min_size=1
hibernate.c3p0.max_size=1
hibernate.c3p0.timeout=10
hibernate.c3p0.max_statements=50
hibernate.c3p0.idle_test_period=10
hibernate.c3p0.unreturned_connection_timeout=1
hibernate.connection.provider_class=org.hibernate.connection.C3P0ConnectionProvider

При каждом новом подключении к приложению создается новый пул. Например, если я установил размер пула 3, 2 подключения к приложению приведут к 6 подключениям, пока приложение не будет закрыто.

Предполагаемое поведение - просто закрывать или повторно использовать соединения после каждой транзакции. Как мне этого добиться?

Ответы [ 3 ]

7 голосов
/ 22 сентября 2010

Во время тестирования я обнаружил, что Hibernate открывает соединение с каждым сеансом, но не закрывает его, независимо от использования метода close ()

При использовании пула соединений вызывается Connection#close() физически не закрывает соединение, а возвращает его в пул для последующего повторного использования.Другими словами, соединение остается открытым, и в этом весь смысл использования пула.


Я вызываю следующее: AnnotationConfiguration (). BuildSessionFactory (). GetCurrentSession ();

Ну, это проблема.Вы создаете SessionFactory снова и снова (каждый создает свой собственный пул), в то время как вы должны создать его только один раз за время существования вашего приложения.Если вы не используете какой-либо конкретный фреймворк, это обычно делается в каком-то служебном классе (знаменитый класс HibernateUtil).

Официальное Hibernate Tutorial содержит очень простой пример такого класса.Или посмотрите этот , который немного богаче.

2 голосов
/ 22 сентября 2010

Концепция пула соединений именно такая. У вас есть пул открытых соединений, и когда вам нужно выполнить транзакцию, вы получаете соединение, уже открытое. Таким образом, вы экономите много времени на открытии и закрытии соединений. Но вы платите цену, чтобы сохранить открытые соединения, когда вы ими не пользуетесь.

У вас есть больше информации о конфигурации c3p0

Обновление Очевидно, ОП вызывал buildSessionFactory один раз за сеанс. Это должно вызываться один раз за время существования приложения.

Вот служебный класс, который создает sessionFactory из Hibernate и предоставляет класс сеанса тому, кто его запрашивает. Это камень для класса DAO.

import org.hibernate.SessionFactory;
import org.hibernate.cfg.AnnotationConfiguration;
import org.hibernate.classic.Session;


public class HibernateUtil {

      private static final SessionFactory sessionFactory;

      static {
          try {
              // Create the SessionFactory from hibernate.cfg.xml
              sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory();
          } catch (Throwable ex) {
              // Make sure you log the exception, as it might be swallowed
              System.err.println("Initial SessionFactory creation failed." + ex);
              throw new ExceptionInInitializerError(ex);
          }
      }

      public static SessionFactory getSessionFactory() {
          return sessionFactory;
      }

      public static Session getCurrentSession() {
          return sessionFactory.getCurrentSession();
      }

}
1 голос
/ 22 сентября 2010

Не рекомендуется использовать пул соединений, если вы хотите закрывать соединение после каждой транзакции. Это именно то, чего хотят избежать пулы соединений ... Вы должны просто отключить C3PO. Hibernate будет обрабатывать соединение самостоятельно (открывать и закрывать как простое соединение JDBC в каждой транзакции)

...