0

目前不太了解这些设置,想知道是否有人可以指出我正确的方向。

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

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>

但是在我的简单小测试应用程序中,它在测试表上运行一个简单的选择 where id = 1,一旦我到达我的第 11 个“搜索”,它就会挂起。

为什么我最多只有 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(); 或者现在应该已经处理了吗?

干杯,伙计们。

4

2 回答 2

2

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

maxPoolSize是一个限制因素;如果您的代码占用了 Connections 而不是close(),C3PO 不知道它们可用于第 11 次搜索。

空闲时间与它无关。C3PO 不能很好地关闭/回收连接,而您似乎仍在使用它,可以吗?空闲时间的目的是杀死已经空闲很长时间的连接,数据库可能已经从它的末端关闭它们。


阻止您的代码关闭会话的具体问题是对 sessionFactory.getCurrentSession(). 您还没有在那里注册当前的 Session,所以它不起作用。

最好直接关闭会话。

在 webapps 中,我使用 Spring OpenSessionInView 模式和一些变体(长会话)。

我建议使用/制作一些定义明确的基础设施来获取 SessionFactory、获取 Sessions(可能绑定到当前线程)以及从当前线程绑定/取消绑定 Sessions。

随着您的应用程序变得越来越大,将所有这些东西放在一个明确定义的地方会有所帮助。

于 2013-08-17T13:09:54.783 回答
1

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

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

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

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

于 2013-08-17T13:11:32.073 回答