Утечка соединения Java Hibernate
Используя Hibernate со Struts2, весь поток выглядит так:
hibernate.cfg.xml
как:
<hibernate-configuration>
<session-factory>
<property name="dialect">org.hibernate.dialect.Oracle9Dialect</property>
<property name="connection.url">jdbc:oracle:thin:@xx.xx.xxx.xx:1521:TEST</property>
<property name="connection.username">xxxx</property>
<property name="connection.password">xxxxyyy</property>
<property name="connection.driver_class">oracle.jdbc.driver.OracleDriver</property>
<mapping class="test.models.administration.Menus" />
<mapping resource="Dual.hbm.xml" />
</session-factory>
</hibernate-configuration>
И для расширения DAO AbstractSimpleGenericDao
:
import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Transaction;
import com.googlecode.s2hibernate.struts2.plugin.annotations.SessionTarget;
import com.googlecode.s2hibernate.struts2.plugin.annotations.TransactionTarget;
@SuppressWarnings("unchecked")
public abstract class AbstractSimpleGenericDao<C, I extends Serializable> {
Class<C> entityClass;
@SessionTarget
protected Session hSession;
@TransactionTarget
protected Transaction hTransaction;
{
entityClass = (Class<C>) ((ParameterizedType)
getClass().getGenericSuperclass()).getActualTypeArguments()[0];
}
public List<C> getAll()
{
try
{
return hSession.createCriteria(entityClass).list();
}
catch (HibernateException e)
{
throw e;
}
}
public C get(I id)
{
try
{
return (C) hSession.get(entityClass, id);
}
catch (HibernateException e)
{
throw e;
}
}
public void save(C object)
{
try
{
hSession.save(object);
}
catch (HibernateException e)
{
hTransaction.rollback();
throw e;
}
}
public void update(C object)
{
try
{
hSession.update(object);
}
catch (HibernateException e)
{
hTransaction.rollback();
throw e;
}
}
public void delete(I id)
{
try
{
C actual = get(id);
hSession.delete(actual);
}
catch (HibernateException e)
{
hTransaction.rollback();
throw e;
}
}
}
Затем расширение выше DAO в моем классе DAO, например:
public class UserRoleDAO extends AbstractSimpleGenericDao<UserRole, UserRoleId> {
public List L() {
try {
String queryString = "from UserRole";
Query queryObject = hSession.createQuery(queryString);
return queryObject.list();
} catch (RuntimeException re) {
throw re;
}
}
Затем в моем классе действий Action, создавая экземпляр DAO и получая список:
public class abc extends ActionSupport{
private UserRoleDAO userRoleDao = new UserRoleDAO();
private List ls=new ArrayList();
public String execute()
{
List ls=userRoleDao.L()
return "success";
}
}
Если я звоню это abc
Класс действия, повторяющиеся щелчки по указанной ссылке меню, затем он вызывает утечку соединения, считается открытым соединением, которое я могу видеть с помощью jProfiler и никогда не закрою. Между тем также, это утечка связей.
StackTrace всех открытых соединений с утечкой, используя jProfiler:
org.hibernate.transaction.JDBCTransaction.begin()
com.googlecode.s2hibernate.struts2.plugin.interceptors.SessionTransactionInjectorInter
ceptor.injectHibernateTransactionByAnnotation(java.lang.Object, org.hibernate.Session, boolean)
com.googlecode.s2hibernate.struts2.plugin.interceptors.SessionTransactionInjectorInter
ceptor.injectHibernateTransactionByAnnotation(java.lang.Object, org.hibernate.Session, boolean)
com.googlecode.s2hibernate.struts2.plugin.interceptors.SessionTransactionInjectorInter
ceptor.intercept(com.opensymphony.xwork2.ActionInvocation)
java.lang.Thread.run()
URL: /project/action-name
Почему Hibernate пропускает эти соединения?
Это похоже на то, что Hibernate поддерживает соединение в сеансе и повторно использует то же соединение, и поэтому, если в то же время, когда я делаю параллельный запрос, если соединение сеанса занято, это приведет к утечке соединений. Это только я предполагаю. Понятия не имею.
1 ответ
В вашей конфигурации hibernate неявно используется DriverManagerConfigurationProvider
, Этот провайдер используется по умолчанию, если вы не настроили его со свойством connection.provider_class
,
Этот провайдер также реализует очень элементарный пул соединений.
Что означает "элементарный пул соединений". Если вы запустите свое приложение, вы можете увидеть в журналах
[DriverManagerConnectionProvider] Using Hibernate built-in connection pool (not for production use!)
[DriverManagerConnectionProvider] Hibernate connection pool size: 20
Вы также можете установить это значение через свойство конфигурации hibernate connection.pool_size
, Но это не ограничивает вас максимальным количеством открытых соединений. Вы можете открыть столько соединений, сколько вам нужно, пока пул пуст. Провайдер будет держать их открытыми, так как он возвращает соединения в пул на closeConnection
если текущий размер пула не превышает значение в свойстве connection.pool_size
, Если текущий размер пула не пуст, вы не сможете открыть любое новое соединение, потому что провайдер соединений возвращает соединение из пула.
Как вы можете видеть сейчас, трудно сказать, что спящий режим с использованием этого провайдера соединений по умолчанию может пропускать соединения, я просто говорю, что это невозможно. Однако это не ограничено количеством открытых соединений.
Чтобы убедиться, что количество подключений ограничено, используйте другого поставщика подключения. Например, вы могли бы использовать C3P0ConnectionProvider
и установить свойство hibernate.c3p0.max_size
ограничивать открытые соединения.