4

我将 GWT 与 Hibernate、c3p0 和 MySQL 一起使用来生成一个受众有限的 Web 应用程序(每天最多 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 个连接,直到应用程序关闭。

预期的行为是在每个事务之后简单地关闭或重用连接。我怎样才能做到这一点?

4

3 回答 3

7

在测试期间,我发现 Hibernate 正在打开与每个会话的连接但没有关闭它,无论使用 close() 方法

使用连接池时,调用Connection#close()不会物理关闭连接,而是将其返回池以供将来重用。换句话说,连接保持打开状态,这就是使用池的全部意义所在。


我称之为: AnnotationConfiguration().buildSessionFactory().getCurrentSession();

嗯,这就是问题所在。您正在SessionFactory一遍又一遍地创建一个(每个都创建自己的池),而您应该在应用程序的整个生命周期内只创建一次。如果您没有使用任何特定的框架,这通常在某些实用程序类(著名的HibernateUtil类)中完成。

官方的Hibernate Tutorial有一个此类类的非常基本的示例。或者看看这个更丰富一点的。

于 2010-09-22T14:07:10.813 回答
2

连接池的概念正是如此。你有一个打开的连接池,当你需要做一个事务时,你会得到一个已经打开的连接。这样,您可以节省大量打开和关闭连接的时间。但是,当您不使用它们时,您会付出代价来保持连接打开。

您有更多关于c3p0 配置的信息

更新显然,OP 在buildSessionFactory每个会话中调用一次。这必须在应用程序的每个生命周期中调用一次。

这是构建 Hibernate 的 sessionFactory 并将会话类提供给任何需要它的人的实用程序类。这是 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();
      }

}
于 2010-09-22T10:42:04.833 回答
1

如果您想在每次事务后关闭连接,则使用连接池不是一个好主意。这正是连接池想要避免的……您应该关闭 C3PO。Hibernate 将自己处理连接(在每个事务中作为简单的 JDBC 连接打开和关闭)

于 2010-09-22T12:47:52.197 回答