Performance 改为OpentransactionPerView@Transactional

Performance 改为OpentransactionPerView@Transactional,performance,spring,hibernate,transactional,open-session-in-view,Performance,Spring,Hibernate,Transactional,Open Session In View,我有一个带有Spring3.1.1和Hibernate4.1的JavaEE应用程序。现在我想加快速度,发现瓶颈是在一个请求中打开和关闭多个事务 现在,我删除了所有的@Transactional注释,并创建了自己的OpenSessionInViewFilter,它可以打开和关闭一个事务 package utils.spring; import java.io.IOException; import javax.servlet.FilterChain; import javax.servlet.

我有一个带有Spring3.1.1和Hibernate4.1的JavaEE应用程序。现在我想加快速度,发现瓶颈是在一个请求中打开和关闭多个事务

现在,我删除了所有的
@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>
但即使我移除了过滤器,Hibernate似乎也不使用池。

我会说不

例如,您将在数据库中保存一些产品或其他内容,并显示一个成功页面或重定向,认为所有内容都已保存。但该事务尚未提交,并且在显示成功消息后仍可能回滚

在Hibernate中,发生这种情况的可能性更大,因为在刷新时间之前不会向数据库写入任何内容,而刷新时间正好在提交之前发生

此外,事务的生命周期将超过必要的时间,如果它锁定了数据库中的行或表,则会阻止处理其他事务,从而导致性能和可伸缩性较差


默认的SpringOpenSessionInviewFilter有什么问题,它允许会话打开,但仍然使用服务级别的短事务?为什么您的请求会打开多个事务?我的问题是,您在一个请求中执行了太多从UI层到服务层的调用。

最后,我以正确的方式配置了我的池。。。解决方案不是向我的hibernate配置中添加一些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>


现在运行起来很有魅力

没错,每个打开的事务大约需要200毫秒=(>>我的问题是,您在一个请求中从UI层到服务层的调用太多。如果您只需要200毫秒来打开一个事务,则在某些地方配置错误。连接池配置是否正确?这200毫秒花在哪里?您测量了吗?是的,添加了一个日志片段,我需要每个请求3个事务:s获取用户、我自己的安全iminterceptor和实际执行工作的rest处理程序的Spring security=(给定日志,获取JDBC连接需要时间。您是否使用连接池?如果是,那么是哪一个,以及如何配置?
<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>