Hibernate无法打开连接

我在hibernate无法打开连接时遇到问题。 我有一个DAO:

public class MyDao extends HibernateDaoSupport { DataSource dataSource; public void setDataSource(DataSource dataSource) { this.dataSource = dataSource; } public MyPOJO findByQuery(int hour) { Query query = this.getSession().createSQLQuery( "SELECT * FROM MyPOJO WHERE someDate >= DATE_SUB(now(), INTERVAL ? HOUR)") .addEntity(MyPOJO.class); List results = query.setInteger(0, hours).list(); return results; } } 

然后在测试用例中调用findByQuery(1)8次,它可以工作,但如果我第9次调用它失败了:

 org.hibernate.exception.GenericJDBCException: Cannot open connection at org.hibernate.exception.SQLStateConverter.handledNonSpecificException(SQLStateConverter.java:103) at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:91) at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43) at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:29) at org.hibernate.jdbc.ConnectionManager.openConnection(ConnectionManager.java:426) at org.hibernate.jdbc.ConnectionManager.getConnection(ConnectionManager.java:144) at org.hibernate.jdbc.AbstractBatcher.prepareQueryStatement(AbstractBatcher.java:139) at org.hibernate.loader.Loader.prepareQueryStatement(Loader.java:1547) at org.hibernate.loader.Loader.doQuery(Loader.java:673) at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:236) at org.hibernate.loader.Loader.doList(Loader.java:2213) at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2104) at org.hibernate.loader.Loader.list(Loader.java:2099) at org.hibernate.loader.custom.CustomLoader.list(CustomLoader.java:289) at org.hibernate.impl.SessionImpl.listCustomQuery(SessionImpl.java:1695) at org.hibernate.impl.AbstractSessionImpl.list(AbstractSessionImpl.java:142) at org.hibernate.impl.SQLQueryImpl.list(SQLQueryImpl.java:152) Caused by: org.apache.commons.dbcp.SQLNestedException: Could not retrieve connection info from pool at org.apache.commons.dbcp.datasources.SharedPoolDataSource.getPooledConnectionAndInfo(SharedPoolDataSource.java:169) at org.apache.commons.dbcp.datasources.InstanceKeyDataSource.getConnection(InstanceKeyDataSource.java:631) at org.apache.commons.dbcp.datasources.InstanceKeyDataSource.getConnection(InstanceKeyDataSource.java:615) at org.springframework.orm.hibernate3.LocalDataSourceConnectionProvider.getConnection(LocalDataSourceConnectionProvider.java:81) at org.hibernate.jdbc.ConnectionManager.openConnection(ConnectionManager.java:423) ... 35 more Caused by: java.util.NoSuchElementException: Timeout waiting for idle object at org.apache.commons.pool.impl.GenericKeyedObjectPool.borrowObject(GenericKeyedObjectPool.java:827) at org.apache.commons.dbcp.datasources.SharedPoolDataSource.getPooledConnectionAndInfo(SharedPoolDataSource.java:165) ... 39 more 

这就是我的hibernate属性:

    org.hibernate.dialect.MySQL5Dialect   thread  false false false true true  org.hibernate.cache.EhCacheProvider  auto   

如果我将release_mode更改为’after_statement’(ala http://docs.jboss.org/hibernate/stable/core/reference/en/html_single/#transactions-connection-release )它会起作用,但我不明白并且觉得这只是一个更大的东西的创可贴,我做错了。

我也尝试刷新并关闭this.getSession()也没有运气。 我可以看到在对findByQuery(1)的所有调用完成后调用close()。

这是在Hibernate 3.2.6,Spring 3.0和MySQL 5.1上。 让我知道我可以提供更多信息。

Javadoc for HibernateDaoSupport.getSession()说:

请注意,这并不是要从HibernateTemplate代码调用,而只是在简单的Hibernate代码中调用。 要么依赖线程绑定的Session,要么将它与releaseSession(org.hibernate.Session)结合使用。

因此,通过getSession()获得的会话应该通过releaseSession()释放:

 public MyPOJO findByQuery(int hour) { Session s = null; try { s = this.getSession(); Query query = s.createSQLQuery( "SELECT * FROM MyPOJO WHERE someDate >= DATE_SUB(now(), INTERVAL ? HOUR)") .addEntity(MyPOJO.class); List results = query.setInteger(0, hours).list(); return results; } finally { if (s != null) this.releaseSession(s); } } 

但处理会话的更好方法是使用HibernateCallback

 public MyPOJO findByQuery(int hour) { return this.getHibernateTemplate().executeFind(new HibernateCallback>() { List doInHibernate(org.hibernate.Session session) { Query query = session.createSQLQuery( "SELECT * FROM MyPOJO WHERE someDate >= DATE_SUB(now(), INTERVAL ? HOUR)") .addEntity(MyPOJO.class); return query.setInteger(0, hours).list(); } }); }