0

Spring 3.1.1 と Hibernate 4.1 を使用した Java EE アプリケーションがあります。今、私は物事をスピードアップしたかったのですが、ボトルネックは 1 つのリクエストで複数のトランザクションの開始と終了であることがわかりました。

@Transactionalここで、すべての注釈を削除しOpenSessionInViewFilter、1 つのトランザクションを開閉する独自の を作成しました。

package utils.spring;

import java.io.IOException;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.orm.hibernate4.SessionFactoryUtils;
import org.springframework.orm.hibernate4.SessionHolder;
import org.springframework.orm.hibernate4.support.OpenSessionInViewFilter;
import org.springframework.transaction.support.TransactionSynchronizationManager;

public class CustomHibernateSessionViewFilter extends OpenSessionInViewFilter {

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {

        SessionFactory sessionFactory = lookupSessionFactory(request);
        boolean participate = false;

        if (TransactionSynchronizationManager.hasResource(sessionFactory)) {
            // Do not modify the Session: just set the participate flag.
            participate = true;
        } else {
            logger.debug("Opening Hibernate Session in OpenSessionInViewFilter");
            Session session = openSession(sessionFactory);
            TransactionSynchronizationManager.bindResource(sessionFactory, new SessionHolder(session));
                    //BEGIN TRANSACTION
            session.beginTransaction();
        }

        try {
            filterChain.doFilter(request, response);
        }

        finally {
            if (!participate) {
                SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager.unbindResource(sessionFactory);
                            // COMMIT
                sessionHolder.getSession().getTransaction().commit();
                logger.debug("Closing Hibernate Session in OpenSessionInViewFilter");
                SessionFactoryUtils.closeSession(sessionHolder.getSession());
            }
        }
    }
}

それは良い考えですか?それはうまくいくようで、物事をスピードアップしました。

トランザクションのログは次のとおりです。

http-bio-8080-exec-3 01/03/2013 11:25:20,947 | DEBUG | org.springframework.orm.hibernate4.HibernateTransactionManager | doGetTransaction | Found thread-bound Session [SessionImpl(PersistenceContext[entityKeys=[],collectionKeys=[]];ActionQueue[insertions=[] updates=[] deletions=[] collectionCreations=[] collectionRemovals=[] collectionUpdates=[] unresolvedInsertDependencies=UnresolvedEntityInsertActions[]])] for Hibernate transaction
http-bio-8080-exec-3 01/03/2013 11:25:20,948 | DEBUG | org.springframework.orm.hibernate4.HibernateTransactionManager | getTransaction | Creating new transaction with name [by2.server.service.UserService.loadUserByUsername]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; ''
http-bio-8080-exec-3 01/03/2013 11:25:20,948 | DEBUG | org.springframework.orm.hibernate4.HibernateTransactionManager | doBegin | Preparing JDBC Connection of Hibernate Session [SessionImpl(PersistenceContext[entityKeys=[],collectionKeys=[]];ActionQueue[insertions=[] updates=[] deletions=[] collectionCreations=[] collectionRemovals=[] collectionUpdates=[] unresolvedInsertDependencies=UnresolvedEntityInsertActions[]])]
http-bio-8080-exec-3 01/03/2013 11:25:21,172 | DEBUG | org.springframework.orm.hibernate4.HibernateTransactionManager | doBegin | Exposing Hibernate transaction as JDBC transaction [org.hibernate.engine.jdbc.internal.proxy.ConnectionProxyHandler@1e7b64f4[valid=true]]
http-bio-8080-exec-3 01/03/2013 11:25:21,188 | DEBUG | org.hibernate.SQL | logStatement | select userentity_.userID as userID5_ from users userentity_ where userentity_.username=?

接続プール

    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-c3p0</artifactId>
        <version>4.1.1.Final</version>
     </dependency>

<property name="hibernateProperties">
        <value>
            hibernate.hbm2ddl.auto=update
            hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
            hibernate.bytecode.use_reflection_optimizer=false
            hibernate.max_fetch_depth=0
            hibernate.c3p0.min_size=5
            hibernate.c3p0.max_size=20
            hibernate.c3p0.timeout=300
            hibernate.c3p0.max_statements=50
            hibernate.c3p0.idle_test_period=3000
            </value>
    </property>

しかし、ビューフィルターで開いているセッションはセッションを閉じているようです

finally {
        if (!participate) {
            SessionHolder sessionHolder =
                    (SessionHolder) TransactionSynchronizationManager.unbindResource(sessionFactory);
            logger.debug("Closing Hibernate Session in OpenSessionInViewFilter");
            SessionFactoryUtils.closeSession(sessionHolder.getSession());
        }
    }

しかし、フィルターを削除しても、Hibernate はプールを使用していないようです。

4

2 に答える 2

1

私はノーと言うでしょう。

たとえば、製品などをデータベースに保存し、成功ページまたはリダイレクトを表示して、すべてが保存されたと考えます。ただし、トランザクションはまだコミットされておらず、成功メッセージが表示された後でもロールバックできます。

また、Hibernate では、コミットの直前に発生するフラッシュ時間までデータベースに何も書き込まれないため、これが発生する可能性はさらに高くなります。

さらに、トランザクションは必要以上に長く存続し、データベース内の行またはテーブルをロックした場合に他のトランザクションが続行できなくなり、パフォーマンスとスケーラビリティが低下します。

デフォルトの Spring OpenSessionInViewFilter の何が問題になっているのでしょうか。これは、セッションを開くことはできますが、サービス レベルの短いトランザクションを引き続き使用します。リクエストが複数のトランザクションを開くのはなぜですか? 私の疑問は、1 回のリクエストで UI レイヤーからサービス レイヤーへの呼び出しが多すぎるということです。

于 2013-03-01T08:45:06.317 に答える
-1

最後に、プールを正しい方法で構成しました...解決策は、いくつかのc3p0プロパティを休止状態の構成に追加することではなく、datasource-beanを置き換えるだけでした

<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close">
    <!-- Connection properties -->
    <property name="driverClass" value="org.postgresql.Driver" />
    <property name="jdbcUrl" value="jdbc:postgresql://localhost:5432/DBNAME" />
    <property name="user" value="xxx" />
    <property name="password" value="xxx" />
    <!-- Pool properties -->
    <property name="minPoolSize" value="5" />
    <property name="maxPoolSize" value="20" />
    <property name="maxStatements" value="50" />
    <property name="idleConnectionTestPeriod" value="3000" />
    <property name="loginTimeout" value="300" />
</bean>

今では魅力のように動作します

于 2013-03-01T12:34:16.060 に答える