0

我有一个带有 Spring 3.1.1 和 Hibernate 4.1 的 Java EE 应用程序。现在我想加快速度,发现瓶颈是在一个请求中打开+关闭多个事务。

现在我删除了所有@Transactional注释并创建了我自己的OpenSessionInViewFilter,它打开和关闭一个事务。

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 有什么问题,它允许会话打开,但仍然使用服务级别的短事务?为什么您的请求会打开多个交易?我的问题是您在单个请求中执行了太多从 UI 层到服务层的调用。

于 2013-03-01T08:45:06.317 回答
-1

最后我以正确的方式配置了我的池......解决方案不是在我的休眠配置中添加一些 c3p0 属性,我只需要替换我的数据源-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 回答