1

使用 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;
    }
      }

然后在我的 struts 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";
        }
            }

如果我正在调用此abcAction 类,通过重复单击指定的菜单链接,它会导致连接泄漏,计为打开的连接,我可以使用 jProfiler 看到,并且永远不会关闭。同时,它也在泄漏连接。

使用 jProfiler 的所有打开的泄漏连接的 StackTrace

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 将连接保持在会话中并重用相同的连接,因此,如果我同时发出并发请求,如果会话连接被占用,它会泄漏连接。这只是我假设。我没有任何想法。

4

1 回答 1

1

在您的休眠配置中隐式使用DriverManagerConfigurationProvider. 默认情况下使用此提供程序,除非您使用属性对其进行配置connection.provider_class

该提供程序还实现了一个非常基本的连接池。

什么意思是“基本的连接池”。如果您运行您的应用程序,您可以在日志中看到

[DriverManagerConnectionProvider] Using Hibernate built-in connection pool (not for production use!)
[DriverManagerConnectionProvider] Hibernate connection pool size: 20

您还可以通过休眠配置属性设置此值connection.pool_size。但它不会限制您打开的最大连接数。当池为空时,您可以打开任意数量的连接。closeConnection除非当前池大小不超过属性中的值,否则提供程序将在返回连接到池时保持它们打开connection.pool_size。一旦当前池大小不为空,您将无法打开任何新连接,因为连接提供程序会从池中返回连接。

正如您现在所看到的,很难说默认情况下使用此连接提供程序的休眠可能会泄漏连接,我只是说这是不可能的。但是,它不受打开连接数的限制。

为确保连接受到限制,请使用不同的连接提供程序。例如,您可以使用C3P0ConnectionProvider并设置该属性hibernate.c3p0.max_size来限制打开的连接。

于 2013-01-28T17:35:26.883 回答