即使设置了maxidletime,当达到maxpoolsize时,Hibernate C3P0也会挂起

时间:2013-08-17 13:01:45

标签: hibernate c3p0

目前还没有真正理解这些设置,想知道是否有人能指出我正确的方向。

我有以下内容,我认为基本上是在说

1:最小池连接数= 5 2:最大池化连接数= 10 3:空闲连接应保持打开多长时间,5秒钟(此时它已关闭并再次可用。

<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
    <property name="driverClass" value="com.mysql.jdbc.Driver" />   
    <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/testdb" />  
    <property name="user" value="root" />   
    <property name="password" value="password" />

    <property name="minPoolSize" value="5" /> 
    <property name="maxPoolSize" value="10" />
    <property name="maxIdleTime" value="5" />
    <property name="maxStatements" value="0" />
</bean>

但是在我的简单小测试应用程序中,只要我在第11个测试表上运行一个简单的选择,其中id = 1 “搜索”,应用程序挂起。

为什么我最多只能连接10个连接,即使我等待超过5秒,为什么没有连接被释放?

- 我班级的片段:

public Object readObject(SessionFactory sessionFactory, String hql, Map<String,Object> args) {
    session = this.openHibernateSession(sessionFactory);

    Query query = session.createQuery(hql);

    Iterator<Entry<String, Object>> it = args.entrySet().iterator();
    while (it.hasNext()) {
        Entry<String, Object> entry = it.next();
        query.setParameter(entry.getKey(), entry.getValue());
    }

    @SuppressWarnings("unchecked")
    List<Object> list = query.list();

    this.closeHibernateSession(sessionFactory); // I don't even know if I should need this!
    if (list!=null && list.size() > 0) {
        return list.get(0);
    } else {
        log4j.warn("readObject: List is NULL.");            
        return null;
    }
}

protected Session openHibernateSession(SessionFactory sessionFactory) {
    Session session = null;
    try {
        session = sessionFactory.getCurrentSession();
    } catch (HibernateException ex) {
        session = sessionFactory.openSession();
    }
    return session;
}

protected void closeHibernateSession(SessionFactory sessionFactory){
    Session session;
    try {
        if (sessionFactory.getCurrentSession()!=null) {
            session = sessionFactory.getCurrentSession();
            session.close();
        }
    } catch (HibernateException ex) {
        log4j.warn("Failed to close current session, set session to null.", ex);

        session = null;
    } 
}

提前干杯。


是的,它几乎是一团糟,所以我把它剥了下来,发现了几个例子并重新开始。

@Transactional
public class UserDaoImpl UserDao {

    @Autowired
    private SessionFactory sessionFactory;

    private Session session;
    private Query query;

    @Override
    public UserDetails getUserDetails(Integer id) {
        session = sessionFactory.getCurrentSession();

        Query query = session.createQuery("FROM UserDetails WHERE id = "+id);

        UserDetails userDetails = (UserDetails) query.list().get(0);

        return userDetails;
    }
}

并对我的application-context.xml进行了一些更改

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

<tx:annotation-driven/> 

现在似乎工作正常,因为在10次连接后我没有挂起。

只是想知道我是否需要打扰session.close();或者现在应该处理这个?

干杯。

2 个答案:

答案 0 :(得分:2)

您可能没有关闭Connections,将它们返回池中。

maxPoolSize是一个限制因素;如果你的代码占用了Connections&amp;没有close()他们,C3PO不知道他们可以进行第11次搜索。

空闲时间与它无关。 C3PO无法很好地关闭/回收连接,而您似乎还在使用它,是吗?空闲时间的目的是消除长时间空闲的连接,数据库可能已经关闭了它们。


阻止您的代码关闭会话的具体问题是对sessionFactory.getCurrentSession()的依赖。您尚未在那里注册当前会话,因此无效。

最好直接关闭会话。

在webapps中,我使用Spring OpenSessionInView模式&amp;一些变种(长会话)。

我建议使用/制作一些定义良好的基础设施来获取SessionFactory,获取Sessions(可能绑定到当前线程),并从当前线程绑定/取消绑定Sessions。

随着您的应用变得越来越大,将所有这些内容放在明确定义的位置会有所帮助。

答案 1 :(得分:1)

我不知道你从哪里得到这个代码,但这是错的。我的猜测是openHibernateSession()总是进入catch块,因此打开一个会话,因为没有当前的会话。

然后closeHibernateSession(),甚至没有在finally块中调用,尝试再次获取当前会话,仍然找不到任何内容,因此不执行任何操作。特别是,它不会关闭openHibernateSession()打开的会话。

因此,只要执行此代码10次,您仍然会打开10个会话,因此有10个连接尚未关闭并返回到连接池。

重新阅读有关Spring和Hibernate集成的文档。你不应该自己打开会话。只使用getCurrentSession(),让Spring处理它们。