我遇到了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<MyPOJO> 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属性:
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">
org.hibernate.dialect.MySQL5Dialect
</prop>
<prop key="hibernate.current_session_context_class">
thread
</prop>
<prop key="hibernate.format_sql">false</prop>
<prop key="hibernate.show_sql">false</prop>
<prop key="hibernate.use_sql_comments">false</prop>
<prop key="hibernate.jdbc.use_get_generated_keys">true</prop>
<prop key="hibernate.cache.use_second_level_cache">true</prop>
<prop key="hibernate.cache.provider_class">
org.hibernate.cache.EhCacheProvider
</prop>
<prop key="hibernate.connection.release_mode">auto</prop>
</props>
</property>
如果我将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上。 让我知道我可以提供更多信息。
答案 0 :(得分:11)
Javadoc for HibernateDaoSupport.getSession()
说:
请注意,这并不意味着 从HibernateTemplate代码调用 而只是在普通的Hibernate中 代码。要么依赖线程绑定 会话或与其结合使用 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<MyPOJO> 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<MyPOJO>>() {
List<MyPOJO> 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();
}
});
}
答案 1 :(得分:0)
我通过更新mysql-connector-java-5.1.23-bin.jar
文件解决了相同的问题。