0

バックエンドとしてSQLを使用し、c3p0接続プーリング(c3p0-0.9.1.1 jar)を使用して、Struts 2 hibernate spring 3を使用してアプリケーションを構築しています。

クエリを実行すると、次のエラーが発生することがあります。クエリを実行するたびに、接続が閉じているかどうかを確認し、閉じている場合は、クエリを実行する前に新しい接続を開きます。


public List<T> find(final Query query, final Object[] values) throws HibernateException, NullPointerException {  
        if (values != null) {  
            for (int i = 0; i < values.length; i++) {  
                query.setParameter(i, values[i]);  
            }  
        }  
        List<T> resultList = null;  
        if (hibernateSession == null || !hibernateSession.isOpen()) {  
            try {  
                openHibernateSession();  
                resultList = query.list();  
            } catch (Exception e) {  
                e.printStackTrace();  
            } finally {  
                closeHibernateSession();  
            }  
        } else {  
            resultList = query.list();  
        }  
        return resultList;  
    }  

public List<T> find(final String queryString, final Object[] values) throws HibernateException {  
        if (hibernateSession == null || !hibernateSession.isOpen()) {  
            openHibernateSession();  
        }  
        Query queryObject = hibernateSession.createQuery(queryString);  
        return find(queryObject, values);  
    }  

private void openHibernateSession() throws HibernateException {  
    try {  
        hibernateSession = HibernateUtil.getSessionFactory().openSession();  
        hibernateSession.setFlushMode(FlushMode.MANUAL);  
        hibernateTransaction = hibernateSession.getTransaction();  
        hibernateTransaction.begin();  
    } catch (Exception e) {    
        e.printStackTrace();  
    }  

}  

private void closeHibernateSession() {  
    try {  

        if (hibernateTransaction != null) {  
            hibernateSession.flush();  
            if (!hibernateTransaction.wasCommitted()) {  
                hibernateTransaction.commit();  
            }  

        }  
        if (hibernateSession != null) {  
            if (hibernateSession.isOpen()) {  
                hibernateSession.close();  
            }  
        }  
    } catch (Exception e) {  
        e.printStackTrace();  
    }  
}  


    <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>  
    <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>  
    <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/projectdb</property>  
    <property name="hibernate.connection.username">root</property>  
    <property name="hibernate.connection.password">root</property>  

    <property name="show_sql">true</property>  
    <property name="format_sql">true</property>   

    <property name="hbm2ddl.auto">update</property>  
    <property name="hibernate.c3p0.min_size">5</property>  
    <property name="hibernate.c3p0.max_size">20</property>  
    <property name="hibernate.c3p0.timeout">1800</property>  
    <property name="hibernate.c3p0.max_statements">50</property>  
    <property name="hibernate.c3p0.idle_test_period">50</property>  
    <property name="hibernate.connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</property>  
    <property name="hibernate.c3p0.acquire_increment">2</property>  

    <property name="hibernate.c3p0.usesTraditionalReflectiveProxies">true</property>  
    <property name="connection.pool_size">20</property>  
    <property name="current_session_context_class">thread</property>  
    <property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>  

    <property name="hibernate.connection.isolation">4</property>  
4

2 に答える 2

0

一時的なインスタンスを保存または更新しようとしている場合は、インスタンスに関連付けられているエンティティが永続的であることを確認してください。これは、デタッチされた参照を使用してエンティティの新しいインスタンスを永続化しようとするユーザーの一般的なエラーです。永続化する一時的なインスタンスまたは切り離されたインスタンスへの参照を設定する前に、永続化コンテキストからエンティティを取得します。

于 2013-04-17T08:05:14.633 に答える
0

おそらく、最も差し迫った問題をかなり簡単に解決できます。closeHibernateSession() で hibernateSession を確実に null に設定してください。これにより、古い閉じられたセッションを再利用しようとするのではなく、クエリ関数が新しいセッションを作成するようになります。

しかし、これだけをしないでください。あなたはもっと大きな問題を抱えています。

休止状態のセッションを整理する方法をより明確にする必要があります。上記のコードから、hibernateSession というメンバー変数があり、複数の呼び出し元または複数のクエリで共有される可能性があることは明らかです。これは、null の場合もそうでない場合もあり、さまざまな関数が遅延して初期化しますが、しばらく時間が経過するまで閉じない場合がありますライン。それはまったくダメです。

最も単純な配置では、セッションをメンバー変数として保持しないでください。ローカル変数として保持します。openHibernateSession() が、finally ブロックで完全に確実に閉じられるセッションを返すようにします。なんらかの理由で、単一の関数呼び出し (もちろん、それぞれがセッションをパラメーターとして受け取る可能性のある他の多くの関数を呼び出す可能性があります) によってカプセル化できるものよりも長く存続するセッションが必要な場合は、非常に注意する必要があります。開いているセッションは確実に close() する必要があり、そのライフサイクルを理解する必要があります。セッションがすでに開いている場合はセッションを使用しますが、それ以外の場合は一時的なセッションを作成する現在のアプローチは良くありません。Session メンバー変数を維持することを主張する場合は、メンバー変数が初期化されるときはいつでも、完全に確実に知る必要があります。

また、トランザクションを理解する必要があります。「close()の前にコミットされていないトランザクションがある場合は、コミットしてください」というものはありません。

また、c3p0-0.9.2.1 への移行を検討してください。

于 2013-04-17T09:08:12.437 に答える