We are using Spring MVC 3.0.5.RELEASE with Hibernate 3.5.4-Final without transactions. Every time we access the database through the hibernateTemplate it creates a new connection and seemingly never closes them.
UPDATE: we've set maxActive and maxIdle to 5. The application will hang when it tries to open the 6th connection. We allow 100 mysql connections.
Our hibernateTemplate is Autowired, so we're not directly managing these connections. Any ideas on how to make sure these connections are closed?
Here's our spring configuration for hibernate:
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<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>5</value>
</property>
<property name="maxIdle">
<value>5</value>
</property>
<property name="removeAbandoned">
<value>true</value>
</property>
<property name="removeAbandonedTimeout">
<value>30</value>
</property>
</bean>
<alias name="dataSource" alias="userInfoDataSource"/>
<!-- Hibernate SessionFactory -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource">
<ref local="dataSource"/>
</property>
<property name="packagesToScan" value="com.domain"/>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.connection.release_mode">after_statement</prop>
<prop key="hibernate.transaction.flush_before_completion">true</prop>
</props>
</property>
</bean>
<bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
Here is our HibernateRepository implementation:
package com.dataAccess.impl;
import org.hibernate.criterion.DetachedCriteria;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.hibernate3.HibernateTemplate;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public abstract class HibernateRepositoryImpl<T> implements com.dataAccess.Repository<T> {
@Autowired
protected HibernateTemplate hibernateTemplate;
public List<T> find(String query) {
return hibernateTemplate.find(query);
}
@Override
public void saveOrUpdate(T ENTITY) {
hibernateTemplate.saveOrUpdate(ENTITY);
}
@Override
public List<T> find(DetachedCriteria criteria) {
return hibernateTemplate.findByCriteria(criteria);
}
@Override
public void delete(T ENTITY) {
hibernateTemplate.delete(ENTITY);
}
}
Here is an example of our we are using it, which seems to leak connections:
package com.dataAccess.impl;
import com.domain.Trigger;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Restrictions;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public class TriggerRepository extends HibernateRepositoryImpl<Trigger> {
public List<Trigger> getActiveTriggers(Integer patientId) {
DetachedCriteria findActiveTriggers = DetachedCriteria.forClass(Trigger.class).add(
Restrictions.and(
Restrictions.eq("patientId", patientId),
Restrictions.eq("active", true)
)
);
return super.find(findActiveTriggers);
}
public List<Trigger> getInActiveTriggers(Integer patientId) {
DetachedCriteria findActiveTriggers = DetachedCriteria.forClass(Trigger.class).add(
Restrictions.and(
Restrictions.eq("patientId", patientId),
Restrictions.eq("active", false)
)
);
return super.find(findActiveTriggers);
}
public Trigger get(Integer triggerId) {
return hibernateTemplate.get(Trigger.class, triggerId);
}
}
The problem ended up being some legacy code which called was chaining several methods together, where the method in the middle of creating the connection -- so the connection was never getting assigned (tough to spot) nor was it ever getting closed. This code was indirectly getting loaded and I wrongly suspected my Hibernate/Spring configuration to be at fault.
If you hit similar issues be wary of lines of code that read:
connectionManager.getConnection().prepareStatement(..).<whatever>
The getConnection() call likely opens a new connection and it nor the prepared statement every have a change to get closed.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With