2

私のアプリケーションはHibernate4.1.7とc3p00.9.1を使用しています。

アプリケーションのhibernate.cfg.xmlファイルのc3p0.max_sizeプロパティを50に設定しましたが、作成されたJDBC接続の数がその値を超えています。また、Hibernate構成でも指定したため、非アクティブ/アイドル接続は削除されません。これが私の設定からの抜粋です:

<property name="c3p0.acquire_increment">1</property>
<property name="c3p0.autoCommitOnClose">false</property>
<property name="c3p0.max_size">50</property>
<property name="c3p0.min_size">1</property>
<property name="c3p0.numHelperThreads">1</property>
<property name="c3p0.maxIdleTime">30</property> 
<property name="c3p0.maxIdleTimeExcessConnections">20</property>
<property name="c3p0.maxConnectionAge">45</property>

コード内のfinallyブロックでセッションとセッションファクトリを明示的に閉じています。SessionFactoryインスタンスを作成するために使用しているクラスは次のとおりです。

package ics.sis.util;

import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;

import ics.global.runtime.Environment;
import ics.util.properties.PropertiesISUWrapper;

public class HibernateSessionFactory {
    private static SessionFactory sessionFactory;
    private static ServiceRegistry serviceRegistry;
    private static final PropertiesISUWrapper ISU_PROPERTIES = new PropertiesISUWrapper(Environment.getName(),"VzAppIntegration"); 

    public static SessionFactory create() {
        Configuration configuration = new Configuration();
        configuration.configure();

        configuration.setProperty("hibernate.connection.url", ISU_PROPERTIES.getUrl());
        configuration.setProperty("hibernate.connection.password", ISU_PROPERTIES.getPassword());

        serviceRegistry = new ServiceRegistryBuilder().applySettings(configuration.getProperties()).buildServiceRegistry();        
        sessionFactory = configuration.buildSessionFactory(serviceRegistry);
        return sessionFactory;
    }

}

データベーストランザクションを実行する主な方法の1つは次のとおりです。

public static int insert(int aidm, String termCode, String wappCode) throws SQLException, ClassNotFoundException {      
        // Initialize session and transaction
        SessionFactory sessionFactory = HibernateSessionFactory.create();
        Session session = sessionFactory.openSession();
        Transaction tx = null;
        int applSeqno = 0;
        Stvwapp wapp = null;

        try {
            tx = session.beginTransaction();

            applSeqno = generateApplSeqNo(session, aidm);
            SarheadId sarheadIdDao = new SarheadId();
            sarheadIdDao.setSarheadAidm(aidm);
            sarheadIdDao.setSarheadApplSeqno((short)applSeqno);

            // Find STVWAPP row by WAPP code
            Query query = session.getNamedQuery("findStvwappByWappCode"); 
            query.setString("wappCode", wappCode);

            if (query.list().size() == 0) {
                throw new RuntimeException("Invalid WAPP code specified: " + wappCode);
            } else {
                wapp = (Stvwapp) query.list().get(0);
            }

            Sarhead sarheadDao = new Sarhead();
            sarheadDao.setId(sarheadIdDao);
            sarheadDao.setSarheadActivityDate(new java.sql.Timestamp(System.currentTimeMillis()));
            sarheadDao.setSarheadAddDate(new java.sql.Timestamp(System.currentTimeMillis()));
            sarheadDao.setSarheadAplsCode("WEB");
            sarheadDao.setSarheadApplAcceptInd("N");
            sarheadDao.setSarheadApplCompInd("N");
            sarheadDao.setSarheadApplStatusInd("N");
            sarheadDao.setSarheadPersStatusInd("N");
            sarheadDao.setSarheadProcessInd("N");
            sarheadDao.setSarheadTermCodeEntry(termCode);
            sarheadDao.setStvwapp(wapp);

            session.save(sarheadDao);
        } finally {
            tx.commit();
            session.close();
            sessionFactory.close(); 
        }

        return applSeqno;
    }

アップデート

c3p0のログレベルをDEBUGに変更して、接続プールでより詳細なログを取得しました。3秒または4秒ごとに、期限切れの接続がないかチェックされます。また、次の行がログに記録されているのがわかります。これは、プールに合計2つの接続があるように見えます。ただし、Toadでは、開いているJDBC接続の総数を監視しており、6と表示されます。したがって、これらの数値の間に不一致がある理由を理解しようとしています。

[Env:DEVL] []-2012-12-06 12:14:07 DEBUG BasicResourcePool:1644-trace com.mchange.v2.resourcepool.BasicResourcePool@7f1d11b9 [管理対象:1、未使用:1、除外:0](例: com.mchange.v2.c3p0.impl.NewPooledConnection@7b3f1264)

4

2 に答える 2

8

あなたはそれを言っています:

アプリケーションの hibernate.cfg.xml ファイルで c3p0.max_size プロパティを 50 に設定しましたが、作成された JDBC 接続の数がその値を超えています。

これは、メソッドでinsertメソッドを呼び出しているために発生しますcreate()。メソッドで毎回create()、次のように新しい sessionFactory を作成します。

 configuration.buildSessionFactory(serviceRegistry);

そのメソッドでは、sessionFactory. sessionFactory インスタンスの作成と終了はどちらも、非常にコストのかかる操作です (終了方法はこちらで確認できます)。

とりわけ、アプリケーションが複数のスレッドで一度に複数のリクエストを処理する場合、各スレッドは独自の sessionFactory を作成します (それぞれが独自のプールを作成します)。そのため、一度に複数の sessionFactory と接続プールがシステムに存在します。アプリケーションの存続期間中に一度だけ作成する必要があります。そのため、プールの複数のコピーがある場合、すべてのプールの合計接続数が、1 つのプールに対して構成した最大制限を超える可能性があります。

HibernateSessionFactory次のようにクラスを書き直すことをお勧めします。

public class HibernateSessionFactory {
    private static SessionFactory sessionFactory = HibernateSessionFactory.create();
    private static ServiceRegistry serviceRegistry;
    private static final PropertiesISUWrapper ISU_PROPERTIES = new PropertiesISUWrapper(Environment.getName(),"VzAppIntegration"); 

    private static SessionFactory create() {
        Configuration configuration = new Configuration();
        configuration.configure();

        configuration.setProperty("hibernate.connection.url", ISU_PROPERTIES.getUrl());
        configuration.setProperty("hibernate.connection.password", ISU_PROPERTIES.getPassword());

        serviceRegistry = new ServiceRegistryBuilder().applySettings(configuration.getProperties()).buildServiceRegistry();        
        return configuration.buildSessionFactory(serviceRegistry);

    }

    public static SessionFactory getSessionFactory(){
       return sessionFactory;
    }

}

メソッドでinsert()は、 を呼び出す代わりにHibernateSessionFactory.create()、単に を呼び出しますHibernateSessionFactory.getSessionFactory()

于 2012-12-06T16:13:39.860 に答える
0

問題は、アプリケーション内で新しいセッション ファクトリを複数回作成していたのに対し、アプリケーションの起動時に 1 回だけ呼び出す必要があったことです。私は、新しいセッションファクトリを作成し、コンテキストが破棄されたときにそれを破棄/閉じた ServletContextListener インターフェースを実装するクラスを作成することになりました。

于 2012-12-06T20:51:47.807 に答える