【问题标题】:Spring 3 MVC Hibernate 3.5.4 hibernateTemplate not closing connections (non-transactional)Spring 3 MVC Hibernate 3.5.4 hibernateTemplate 不关闭连接(非事务性)
【发布时间】:2011-08-24 03:08:54
【问题描述】:

我们使用 Spring MVC 3.0.5.RELEASE 和 Hibernate 3.5.4-Final 没有事务。每次我们通过 hibernateTemplate 访问数据库时,它都会创建一个新连接并且似乎永远不会关闭它们。

更新:我们已将 maxActive 和 maxIdle 设置为 5。应用程序在尝试打开第 6 个连接时将挂起。我们允许 100 个 mysql 连接。

我们的 hibernateTemplate 是自动装配的,所以我们不直接管理这些连接。有关如何确保这些连接已关闭的任何想法?

这是我们的休眠弹簧配置:

<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>

这是我们的 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);
  }
}

这是我们正在使用它的一个示例,它似乎泄漏了连接:

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);
  }
}

【问题讨论】:

    标签: java hibernate spring-mvc


    【解决方案1】:

    我相信,如果您不使用 transactionManager,那么您应该在 HibernateRepositoryImpl 类中的每个操作之后关闭 Hibernate 会话。

    在大多数情况下,您所拥有的可能会被视为错误 - 您正在打开新的 Hibernate 会话,但它们从未关闭 - 您看到实际对数据库执行的 SQL 语句的唯一原因是因为您拥有hibernate.transaction.flush_before_completion 属性设置为 true。

    【讨论】:

    • 感谢您的回复。不幸的是,我不知道如何关闭连接,因为一切都是通过 spring 管理和自动连接的,而 HibernateTemplate 没有提供任何我能说的机制。我已将项目移动到使用事务,但这也不能解决问题。我现在正在尝试利用我的应用程序容器(Tomcat 6)来管理连接并提供一种通过 JNDI 访问它们的方法,但是 Spring 无法找到 dataSource bean。
    • 我已将项目转移到使用事务,但这也不能解决问题你看过static.springsource.org/spring/docs/current/… 吗?通常你可以简单地用@Transactional注释(服务)方法;确保连接TransactionManager
    • 是的,当我移动事物以使用事务时,我将所有 Repository 类标记为 @Transactional 并连接了 Hibernate TransactionManager。我什至尝试过迁移到 C3P0 的连接池,但还是不行。我目前正在剥离所有内容并逐个添加片段,以查看是否可以查明何时出现问题。
    • 如果您打开 org.hibernate 和 org.springframework 上的日志记录,您是否看到 Hibernate 会话被关闭?
    • 感谢您的回复马特。经过一堆挖掘之后,罪魁祸首是一些遗留代码,它链接了一个创建连接的调用(因此它从未被分配或释放)。结束的遗留代码在几种情况下被间接加载(这让我相信这是罪魁祸首是休眠/弹簧方面)。
    【解决方案2】:

    问题最终是一些遗留代码,它调用了将多个方法链接在一起,其中该方法在创建连接的中间——因此连接从未被分配(很难发现),也从未被关闭。这段代码被间接加载了,我错误地怀疑我的 Hibernate/Spring 配置有问题。

    如果您遇到类似问题,请注意以下代码行:

    connectionManager.getConnection().prepareStatement(..).<whatever>
    

    getConnection() 调用可能会打开一个新连接,并且它和准备好的语句都需要更改才能关闭。

    【讨论】:

    • 好收获!很高兴在与您讨论后,我只输给了 Google 30 分钟。 :)
    • 另外,我想知道您是否只是将 connectionManager 引用更改为 Spring 提供的 DataSource 是否会修复它。
    • 我们更新它以使用 spring 提供的数据源(问题仍然存在,直到我们拆分链接调用,以便我们可以显式关闭连接)。非常感谢您前几天的帮助!
    【解决方案3】:

    另外请确保您创建的HibernateTemplate 实例不超过一个, 我

    ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("META-INF/spring/applicationContext.xml");
    Object o=context.getBean("hibernateTemplate");
    

    对象o 必须缓存在某处,并在您的应用代码请求hibernatetemplate 实例时返回。

    谢谢

    【讨论】:

      猜你喜欢
      • 2014-09-11
      • 2011-05-19
      • 1970-01-01
      • 2017-02-17
      • 1970-01-01
      • 1970-01-01
      • 2012-03-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多