到达max_size时c3p0没有释放连接

时间:2015-03-17 17:39:52

标签: java spring hibernate c3p0

我试图用一种方法在数据库上执行10次get。 我使用的是Hibernate 3.5.x和Spring 3.2.13以及c3p0 0.9.5。

我的hibernate.cfg.xml包含以下内容:

<property name="hibernate.c3p0.acquire_increment">1</property>
<property name="hibernate.c3p0.idle_test_period">300</property>
<property name="hibernate.c3p0.max_size">10</property>
<property name="hibernate.c3p0.max_statements">0</property>
<property name="hibernate.c3p0.min_size">10</property>
<property name="hibernate.c3p0.timeout">600</property>

这一切都可以正常使用来自c3p0的调试说:

[managed: 10, unused: 0, excluded: 0] 
[managed: 10, unused: 1, excluded: 0] 
[managed: 10, unused: 2, excluded: 0] 
[managed: 10, unused: 3, excluded: 0] 
[managed: 10, unused: 4, excluded: 0] 
[managed: 10, unused: 5, excluded: 0] 
[managed: 10, unused: 6, excluded: 0] 
[managed: 10, unused: 7, excluded: 0] 
[managed: 10, unused: 8, excluded: 0] 
[managed: 10, unused: 9, excluded: 0]

这一切都很快发生(少于0.5秒)

但如果我添加一个额外的获得,即11,那么我得到以下内容:

[managed: 10, unused: 0, excluded: 0] repeatedly

在连接超时之前它不会改变。

我正在使用Springs Transaction Manager:

<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory" />
</bean>

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

并使用以下基本上调用findOne()

的内容
public abstract class AbstractDAO<T extends Serializable> {
    private Class< T > clazz;

    @Autowired
    private SessionFactory sessionFactory;

    public void setSessionFactory(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }

    public void setClazz(final Class<T> clazzToSet) {
        clazz = clazzToSet;
    }

    @Transactional
    public T findOne(final long id) {
        return (T) getCurrentSession().get(clazz, id);
    }

...
}

请告诉我其他信息可能有助于诊断。

我可以做错什么?

2 个答案:

答案 0 :(得分:1)

您正在泄露连接。

您未能关闭()您的Connections。 (请在一个finally块中强有力地关闭()它们,以便保证对close()的调用 - 即最终不能被先前的Exception跳过 - 或者更好的是如果Java 7+使用try-with-resources

注意:在Hibernate中,它是Session,它包装了Connections,你必须确保得到close()ed。

答案 1 :(得分:1)

所以看起来你不能在同一个线程中使用更多hibernate.c3p0.max_size连接,即如果hibernate.c3p0.max_size设置为10,那么你不能在同一个线程中有11个获取。我猜c3p0只在线程完成后才释放连接。

我测试的方法是让10个方法进入该方法,然后睡眠15秒。我执行了两次方法,第一个方法使用10个连接。 15秒后,该方法完成,第二次执行成功运行另外10个连接,然后在15秒后释放。

我想我能理解为什么会这样。我想我将不得不重构/重新设计我对连接的使用......

<强>更新 我找到了这个hibernate.connection.release_mode属性,我将其设置为after_statement。这似乎在执行后释放连接。有关详细信息,请参阅here