Spring 3 MVC Hibernate 3.5.4 hibernateTemplate не закрывает соединения (нетранзакционные) - PullRequest
3 голосов
/ 12 мая 2011

Мы используем Spring MVC 3.0.5.RELEASE с Hibernate 3.5.4-Final без транзакций. Каждый раз, когда мы обращаемся к базе данных через hibernateTemplate, она создает новое соединение и, похоже, никогда не закрывает их.

ОБНОВЛЕНИЕ: мы установили maxActive и maxIdle равными 5. Приложение будет зависать при попытке открыть 6-е соединение. Мы разрешаем 100 подключений mysql.

Наш hibernateTemplate имеет функцию Autowired, поэтому мы не управляем напрямую этими соединениями. Любые идеи о том, как убедиться, что эти соединения закрыты?

Вот наша весенняя конфигурация для гибернации:

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

Ответы [ 3 ]

3 голосов
/ 14 мая 2011

В итоге проблема заключалась в том, что какой-то устаревший код, который вызывал, связывал воедино несколько методов, где метод находился в процессе создания соединения, поэтому соединение никогда не назначалось (трудно определить) и не закрывалось. Этот код загружался косвенно, и я ошибочно подозревал, что моя конфигурация Hibernate / Spring ошибочна.

Если вы сталкиваетесь с подобными проблемами, остерегайтесь строк кода, которые читают:

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

Вызов getConnection (), скорее всего, открывает новое соединение, и у него и у подготовленного оператора есть изменения, которые нужно закрыть.

0 голосов
/ 21 июня 2011

Также убедитесь, что вы не создаете более одного экземпляра HibernateTemplate, i

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

Объект o должен быть где-то кэширован и возвращен, когда код вашего приложения запрашиваетэкземпляр hibernatetemplate.

Спасибо

0 голосов
/ 12 мая 2011

Я полагаю, что если вы не используете транзакционный менеджер, вам следует закрывать сеанс Hibernate после каждой операции в вашем классе HibernateRepositoryImpl.

То, что у вас, вероятно, будет считаться ошибкой в ​​большинстве ситуаций - вы открываете новые сеансы Hibernate, но они никогда не закрываются - единственная причина, по которой вы видите, что операторы SQL фактически выполняются в базе данных, заключается в том, чтоу вас есть свойство hibernate.transaction.flush_before_completion, установленное в true.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...