[英]Spring 3 MVC Hibernate 3.5.4 hibernateTemplate not closing connections (non-transactional)
We are using Spring MVC 3.0.5.RELEASE with Hibernate 3.5.4-Final without transactions. 我们在没有事务的情况下使用Spring MVC 3.0.5.RELEASE和Hibernate 3.5.4-Final。 Every time we access the database through the hibernateTemplate it creates a new connection and seemingly never closes them.
每次我们通过hibernateTemplate访问数据库时,它都会创建一个新连接,并且似乎永远不会关闭它们。
UPDATE: we've set maxActive and maxIdle to 5. The application will hang when it tries to open the 6th connection. 更新:我们将maxActive和maxIdle设置为5.应用程序在尝试打开第6个连接时将挂起。 We allow 100 mysql connections.
我们允许100个mysql连接。
Our hibernateTemplate is Autowired, so we're not directly managing these connections. 我们的hibernateTemplate是Autowired,因此我们不直接管理这些连接。 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: 这是我们的HibernateRepository实现:
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.
这段代码是间接加载的,我错误地怀疑我的Hibernate / Spring配置有问题。
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. getConnection()调用可能会打开一个新连接,并且每个准备好的语句都有一个更改才能关闭。
I believe that if you aren't using a transactionManager then you should be closing the Hibernate session after each of the operations in your HibernateRepositoryImpl
class. 我相信如果您没有使用transactionManager,那么您应该在
HibernateRepositoryImpl
类中的每个操作之后关闭Hibernate会话。
What you have would probably be considered a bug in most situations - you are opening new Hibernate sessions, but they are never being closed - the only reason why you are seeing the SQL statements actually executed against the database is because you have the hibernate.transaction.flush_before_completion
property set to true. 你在大多数情况下可能会被认为是一个错误 - 你正在打开新的Hibernate会话,但它们永远不会被关闭 - 你看到实际对数据库执行的SQL语句的唯一原因是因为你有
hibernate.transaction.flush_before_completion
属性设置为true。
Also please make sure that you are not creating more than one instance of HibernateTemplate
, i 另外请确保您没有创建多个
HibernateTemplate
实例,i
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("META-INF/spring/applicationContext.xml");
Object o=context.getBean("hibernateTemplate");
The object o
has to be cached somewhere and returned when your app code is asking for instance of hibernatetemplate
. 对象
o
必须在某处缓存,并在您的应用程序代码要求hibernatetemplate
实例时返回。
Thanks 谢谢
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.