如何防止Hibernate + c3p0 + MySql创建大量睡眠连接?

我正在使用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个连接,直到应用程序关闭为止。

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

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

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


我调用以下内容:AnnotationConfiguration()。buildSessionFactory()。getCurrentSession();

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

官方的Hibernate教程有一个非常基本的类这样的例子。 或者看看这个更富有的。

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

您有关于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(); } } 

如果要在每次事务后关闭连接,则使用连接池不是一个好的理想选择。 连接池想要避免的是什么……你应该关闭C3PO。 Hibernate将自己处理连接(在每个事务中打开和关闭简单的JDBC连接)