0

我有一個Java EE應用程序與Spring 3.1.1和Hibernate 4.1。現在我想加快速度,發現瓶頸在一個請求中打開並關閉多個事務。OpentransactionPerView而不是@Transactional

現在我刪除了所有@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 [[email protected]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似乎沒有使用該池。

回答

1

我會說不。

例如,你可以節省一些產品或任何在數據庫中,並顯示成功頁面或重定向,自以爲一切已保存。但是交易將不會被提交,並且在之後,您仍然可以回滾顯示成功消息。

而且與Hibernate,這種情況發生的概率更大,因爲什麼都不會被寫入到數據庫中,直到沖洗時間,這將只是在提交前發生。

此外,該交易將活得比必要,以防止其他交易情況procees它放在行或表鎖在數據庫中,從而導致較差的性能和可擴展性。

默認的Spring OpenSessionInViewFilter有什麼問題,它可以讓會話打開,但仍然使用服務級別的短事務?爲什麼你的請求打開多個交易?我的問題是,你在一個請求中從UI層到服務層進行了太多的調用。

+0

那是正確的,每個事務打開需要大約200ms =(>>我的問題是,你在一個請求中從UI層到服務層進行了太多的調用 – wutzebaer 2013-03-01 09:29:45

+0

如果你需要某些東西配置錯誤200ms只是爲了打開一個事務,連接池配置是否正確?這些200ms花費在哪裏?你有沒有測量? – 2013-03-01 10:06:20

+0

是的,增加了一個日誌片段,我需要每個請求3個交易:獲取用戶的春天安全,我自己的安全imnterceptor,以及其餘的處理程序,實際上這樣做的工作=( – wutzebaer 2013-03-01 10:32:28

0

最後我配置我的池以正確的方式...的解決辦法不是一些C3P0屬性添加到我的休眠的配置,我不得不現在更換我的數據源豆就像一個魅力

<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> 

運行