1

Struts2でHibernateを使用すると、フロー全体は次のようになります。

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 に答える