我们的项目使用的是Hibernate 3.2.7.ga,而Springs则是2.5.6来处理数据库交互。 在生产服务器上,在连接了一定数量的用户(不超过10个)后,我们开始收到以下错误:
javax.servlet.ServletException: javax.servlet.ServletException:
org.springframework.transaction.CannotCreateTransactionException:
Could not open Hibernate Session for transaction; nested exception is org.hibernate.exception.GenericJDBCException: Cannot open connection
源于:
org.postgresql.util.PSQLException: FATAL:
connection limit exceeded for non-superusers
阅读类似问题我发现罪魁祸首通常是不使用池化数据源。所以我去检查弹簧配置并找到了 -
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<!-- ========================= RESOURCE DEFINITIONS ========================= -->
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location"><value>/WEB-INF/jdbc.properties</value></property>
</bean>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" > <!--class="org.springframework.jdbc.datasource.DriverManagerDataSource">-->
<property name="driverClassName"><value>${jdbc.driverClassName}</value></property>
<property name="url"><value>${jdbc.url}</value></property>
<property name="username"><value>${jdbc.username}</value></property>
<property name="password"><value>${jdbc.password}</value></property>
</bean>
<!-- Hibernate SessionFactory -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource"><ref local="dataSource"/></property>
<property name="mappingResources">
<list>
....
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
</props>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory"><ref local="sessionFactory"/></property>
</bean>
<!-- ========================= BUSINESS OBJECT DEFINITIONS ========================= -->
<bean id="HibernateSpringDaoTarget" class="cnr.dao.SpringHibernateDAOImpl">
<property name="sessionFactory"><ref local="sessionFactory"/></property>
</bean>
<bean id="SpringHibernateDao" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager"><ref local="transactionManager"/></property>
<property name="target"><ref local="HibernateSpringDaoTarget"/></property>
<property name="transactionAttributes">
<props>
<prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="load*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="store*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
</beans>
SpringHibernateDAOImpl 扩展 HibernateDaoSupport 并包含我们所有的hibernate查询和更新。在代码中,它通过调用
来使用WebApplicationContextUtils.getRequiredWebApplicationContext(httpRequest.getSession().getServletContext()).getBean("SpringHibernateDao");
spring配置将指示使用的数据源是Commons的基本数据源,它应该支持连接池。
关于我应该检查什么的任何想法?
[评论更新] 至于最大活动连接,我将配置文件更改为
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" > <!--class="org.springframework.jdbc.datasource.DriverManagerDataSource">-->
<property name="driverClassName"><value>${jdbc.driverClassName}</value></property>
<property name="url"><value>${jdbc.url}</value></property>
<property name="username"><value>${jdbc.username}</value></property>
<property name="password"><value>${jdbc.password}</value></property>
<property name="maxActive"><value>1</value></property>
</bean>
然而,这并没有解决问题。
Hibernate是3.2.7.ga,Springs是2.5.6
一些典型的db代码是:
public void save(LikeRecord like){
getHibernateTemplate().save(like);
}
public boolean existsUserWithEmail(String email){
Criteria crit = getSession().createCriteria(Utente.class);
crit.add(Restrictions.eq("email", email));
Utente user = (Utente) crit.uniqueResult();
if(user==null)return false;
else return true;
}
public boolean existsUserWithUsername(String userName){
Criteria crit = getSession().createCriteria(Utente.class);
crit.add(Restrictions.eq("loginid", userName));
Utente user = (Utente) crit.uniqueResult();
if(user==null)return false;
else return true;
}
至于交易和池管理器我的印象是这是由applicationContext中定义的spring bean在引擎盖下处理的,但我不是很确定。