spring攔截器中的事務管理

探討一下spring攔截器中的數據庫操做和事務管理。
你們知道spring中的事務管理是經過AOP代理來實現的,對被代理對象的每一個方法進行攔截,在方法執行前啓動事務,方法執行完後根據是否有異常和異常的種類進行提交或回滾。

如 果要在方法執行前或後或拋出異常後加上一個本身的攔截器,或者一個環繞攔截器,在攔截器中執行一些操做,好比執行一些數據庫操做,記錄一些信息,這些操做 經過調用一個服務類的方法來執行,這個方法也在spring事務管理攔截器的管理之下,那麼這個記錄方法須要在另外一個事務中進行,而不是與被攔截方法在同 一個事務中,否則若是被攔截方法拋出異常須要回滾時,所做的記錄也會被回滾,固然有時候確實須要同時回滾,那就要放在同一個事務中。

這 和本身的攔截器和事務管理的攔截器的執行順序有必定關係,spring事務管理攔截器是一個環繞通知,在被攔截方法執行前啓動事務,執行後完成事務,若是 本身的攔截器被spring事務管理攔截器包圍在裏面,那麼在本身的攔截器運行時,spring已經啓動了一個事務,若是你的記錄信息方法須要與被攔截方 法同在一個事務中,將你的記錄信息方法的事務傳播屬性設爲默認的REQUIRED就能夠了;
若是你記錄信息的方法須要單獨的一個事務環境,那就 要把事務傳播屬性設爲REQUIRES_NEW了,這樣spring事務管理器會新建一個事務,而且新建一個session鏈接,由於一個數據庫鏈接不可 能同時有兩個事務,記錄信息完了提交事務而且把新建的session鏈接關閉,本身的攔截器退出後繼續執行被攔截的方法或它的事務處理。

相 反若是本身的攔截器在spring事務管理攔截器的外面,那麼記錄信息的方法會在一個單獨的事務中執行,並提交,無論它的事務傳播屬性是 REQUIRES_NEW仍是REQUIRED,由於與被攔截方法的事務處理沒有交叉,而且可使用同一個session鏈接若是是 OpenSessionInViewFilter。

因此若是記錄信息和被攔截方法要在不一樣事務中執行,分別提交,那麼最好將本身的攔截 器設在spring事務管理器攔截器的外面;若是須要將記錄信息和被攔截方法在同一個事務中處理,必須將本身的攔截器被包圍在spring事務管理攔截器 中,而且記錄信息方法的事務傳播屬性爲默認的REQUIRED。

設置攔截器的執行順序可讓攔截器處理類實現 org.springframework.core.Ordered接口,在spring配置文件的AOP設置中設定本身的攔截器和spring事務管理 攔截器的執行順序,將本身的攔截的序號排在spring事務管理的前面,就能夠將該攔截器放到事務管理攔截器的外面執行了,對於before通知方式會先 於事務管理攔截器執行,對於after returning和after和after throwing通知方式會後於事務管理攔截器的執行,對於arount通知方式會包圍事務管理攔截器執行。

下面是一個異常攔截器的例子。
有 位朋友提到在spring異常攔截器中更新數據不可以提交,作了一下測試,測試環境基本是這樣:一個用戶登陸的功能,spring對service中的每 個方法進行事務管理,在用戶檢測的service方法上同時加上一個異常攔截器,當用戶不存在或密碼不正確時用戶檢測方法會拋出異常,異常攔截器捕獲到該 異常,同時記錄一些日誌。
spring配置文件相關: java

Java代碼 複製代碼
  1. <!-- 事務管理 -->   
  2. <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">    
  3.     <property name="sessionFactory" ref="sessionFactory"></property>   
  4. </bean>   
  5.   
  6. <!-- 事務通知 -->   
  7. <tx:advice id="txAdvice" transaction-manager="transactionManager">   
  8.     <tx:attributes>   
  9.         <tx:method name="get*" read-only="true"/>   
  10.         <tx:method name="*" propagation="REQUIRES_NEW" rollback-for="Exception"/>   
  11.     </tx:attributes>   
  12. </tx:advice>   
  13.   
  14. <!-- aop代理設置 -->   
  15. <aop:config proxy-target-class="true">   
  16.     <aop:pointcut id="txPointcut" expression="execution(* com.hbs..*Service.*(..))"/>   
  17.     <aop:pointcut id="logPointcut" expression="execution(* com.hbs.customer..*Service.*(..))"/>   
  18.     <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut" order="1"/>   
  19.     <aop:aspect id="logAspect" ref="logInterceptor" order="2" >   
  20.         <aop:after-throwing   
  21.             pointcut-ref="logPointcut"    
  22.             method="serviceIntercept" />   
  23.     </aop:aspect>   
  24. </aop:config>   
  25.   
  26. <!-- log攔截器類 -->   
  27. <bean id="logInterceptor" class="com.hbs.eventlog.EventLogInterceptor">   
  28.     <property name="service" ref="logService"></property>   
  29. </bean>  
[java] view plain copy
  1. <!-- 事務管理 -->  
  2. <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">   
  3.     <property name="sessionFactory" ref="sessionFactory"></property>  
  4. </bean>  
  5.   
  6. <!-- 事務通知 -->  
  7. <tx:advice id="txAdvice" transaction-manager="transactionManager">  
  8.     <tx:attributes>  
  9.         <tx:method name="get*" read-only="true"/>  
  10.         <tx:method name="*" propagation="REQUIRES_NEW" rollback-for="Exception"/>  
  11.     </tx:attributes>  
  12. </tx:advice>  
  13.   
  14. <!-- aop代理設置 -->  
  15. <aop:config proxy-target-class="true">  
  16.     <aop:pointcut id="txPointcut" expression="execution(* com.hbs..*Service.*(..))"/>  
  17.     <aop:pointcut id="logPointcut" expression="execution(* com.hbs.customer..*Service.*(..))"/>  
  18.     <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut" order="1"/>  
  19.     <aop:aspect id="logAspect" ref="logInterceptor" order="2" >  
  20.         <aop:after-throwing  
  21.             pointcut-ref="logPointcut"   
  22.             method="serviceIntercept" />  
  23.     </aop:aspect>  
  24. </aop:config>  
  25.   
  26. <!-- log攔截器類 -->  
  27. <bean id="logInterceptor" class="com.hbs.eventlog.EventLogInterceptor">  
  28.     <property name="service" ref="logService"></property>  
  29. </bean>  


攔截器類:web


Java代碼 複製代碼
  1. public class EventLogInterceptor implements Ordered {   
  2.   
  3.     private int order = 1;   
  4.        
  5.     private EventLogService service;   
  6.        
  7.     public Object serviceIntercept(ProceedingJoinPoint point) throws Throwable{   
  8.         if(point instanceof MethodInvocationProceedingJoinPoint){   
  9.             MethodInvocationProceedingJoinPoint mpoint = (MethodInvocationProceedingJoinPoint)point;   
  10.             //   
  11.         }   
  12.         try {    
  13.             System.out.println("記錄日誌開始");   
  14.             service.eventLog();   
  15.             System.out.println("記錄日誌結束");   
  16.         }catch(Exception ex) {   
  17.             ex.printStackTrace();   
  18.         }   
  19.         return null;   
  20.     }   
  21.        
  22.     public void setOrder(int order){   
  23.         this.order = order;   
  24.     }   
  25.     public int getOrder() {   
  26.         return order;   
  27.     }   
  28.     public EventLogService getService() {   
  29.         return service;   
  30.     }   
  31.     public void setService(EventLogService service) {   
  32.         this.service = service;   
  33.     }   
  34. }  
[java] view plain copy
  1. public class EventLogInterceptor implements Ordered {  
  2.   
  3.     private int order = 1;  
  4.       
  5.     private EventLogService service;  
  6.       
  7.     public Object serviceIntercept(ProceedingJoinPoint point) throws Throwable{  
  8.         if(point instanceof MethodInvocationProceedingJoinPoint){  
  9.             MethodInvocationProceedingJoinPoint mpoint = (MethodInvocationProceedingJoinPoint)point;  
  10.             //  
  11.         }  
  12.         try {   
  13.             System.out.println("記錄日誌開始");  
  14.             service.eventLog();  
  15.             System.out.println("記錄日誌結束");  
  16.         }catch(Exception ex) {  
  17.             ex.printStackTrace();  
  18.         }  
  19.         return null;  
  20.     }  
  21.       
  22.     public void setOrder(int order){  
  23.         this.order = order;  
  24.     }  
  25.     public int getOrder() {  
  26.         return order;  
  27.     }  
  28.     public EventLogService getService() {  
  29.         return service;  
  30.     }  
  31.     public void setService(EventLogService service) {  
  32.         this.service = service;  
  33.     }  
  34. }  


service方法中的事務傳播屬性都設爲要求新建事務,spring事務管理切面攔截器的order設爲1,而log攔截器的 order設爲2,這意味着這兩個要同時執行時,先執行事務攔截器,後執行log攔截器,因爲事務管理是一個環繞通知(around),其實是log攔 截器被包圍在事務管理攔截器中。spring


一個不正確的用戶登陸時,打印的日誌:數據庫


03:35:16,562 DEBUG OpenSessionInViewFilter:253 - Using SessionFactory 'sessionFactory' for OpenSessionInViewFilterexpress


03:35:16,562 DEBUG OpenSessionInViewFilter:196 - Opening single Hibernate Session in OpenSessionInViewFilterapache


03:35:16,562 DEBUG SessionFactoryUtils:333 - Opening Hibernate Sessionsession


03:35:16,562 DEBUG TransactionSynchronizationManager:166 - Bound value [org.springframework.orm.hibernate3.SessionHolder@1fee2db] for key [org.hibernate.impl.SessionFactoryImpl@1fe3238] to thread [http-8088-Processor25]app


03:35:16,562 DEBUG TransactionSynchronizationManager:139 - Retrieved value [org.springframework.orm.hibernate3.SessionHolder@1fee2db] for key [org.hibernate.impl.SessionFactoryImpl@1fe3238] bound to thread [http-8088-Processor25]ide


03:35:16,562 DEBUG HibernateTransactionManager:390 - Found thread-bound Session [org.hibernate.impl.SessionImpl@dfbabd] for Hibernate transaction測試


03:35:16,578 DEBUG HibernateTransactionManager:292 - Using transaction object [org.springframework.orm.hibernate3.HibernateTransactionManager$HibernateTransactionObject@5cd7f9]


03:35:16,578 DEBUG HibernateTransactionManager:320 - Creating new transaction with name [com.hbs.customer.CustomerService.customerLogin]


03:35:16,578 DEBUG HibernateTransactionManager:440 - Preparing JDBC Connection of Hibernate Session [org.hibernate.impl.SessionImpl@dfbabd]


03:35:16,578 DEBUG HibernateTransactionManager:510 - Exposing Hibernate transaction as JDBC transaction [org.apache.commons.dbcp.PoolableConnection@1501026]


03:35:16,578 DEBUG TransactionSynchronizationManager:166 - Bound value [org.springframework.jdbc.datasource.ConnectionHolder@1672c01] for key [org.apache.commons.dbcp.BasicDataSource@54cbb9] to thread [http-8088-Processor25]


03:35:16,578 DEBUG TransactionSynchronizationManager:219 - Initializing transaction synchronization


03:35:16,578 DEBUG TransactionInterceptor:275 - Getting transaction for [com.hbs.customer.CustomerService.customerLogin]


用戶登陸


03:35:16,578 DEBUG TransactionSynchronizationManager:139 - Retrieved value [org.springframework.orm.hibernate3.SessionHolder@1fee2db] for key [org.hibernate.impl.SessionFactoryImpl@1fe3238] bound to thread [http-8088-Processor25]


03:35:16,578 DEBUG TransactionSynchronizationManager:139 - Retrieved value [org.springframework.orm.hibernate3.SessionHolder@1fee2db] for key [org.hibernate.impl.SessionFactoryImpl@1fe3238] bound to thread [http-8088-Processor25]


03:35:16,578 DEBUG HibernateTemplate:354 - Found thread-bound Session for HibernateTemplate


03:35:16,578 DEBUG SQL:393 - select this_.CUSTOMER_ID as CUSTOMER1_5_0_, this_.CUSTOMER_GROUP_ID as CUSTOMER2_5_0_, this_.CUSTOMER_PASSWORD as CUSTOMER3_5_0_, this_.CUSTOMER_NAME as CUSTOMER4_5_0_, this_.CUSTOMER_DESCRIPTION as CUSTOMER5_5_0_, this_.CUSTOMER_KIND as CUSTOMER6_5_0_, this_.CUSTOMER_SEX as CUSTOMER7_5_0_, this_.PHONE as PHONE5_0_, this_.MOBILE as MOBILE5_0_, this_.ADDRESS as ADDRESS5_0_, this_.EMAIL as EMAIL5_0_, this_.CONFIRM_TYPE as CONFIRM12_5_0_, this_.CREATE_TIME as CREATE13_5_0_, this_.GROUP_TIME as GROUP14_5_0_, this_.FIRST_TIME as FIRST15_5_0_, this_.LAST_TIME as LAST16_5_0_, this_.LOGIN_COUNT as LOGIN17_5_0_, this_.CREDIT_VALUE as CREDIT18_5_0_, this_.CUMULATE_VALUE as CUMULATE19_5_0_, this_.STATUS as STATUS5_0_, this_.NOTES as NOTES5_0_ from hbs.hbs_customer this_ where this_.CUSTOMER_ID=? and this_.CUSTOMER_PASSWORD=?


03:35:16,593 DEBUG HibernateTemplate:378 - Not closing pre-bound Hibernate Session after HibernateTemplate


記錄日誌開始

03:35:16,593 DEBUG TransactionSynchronizationManager:139 - Retrieved value [org.springframework.orm.hibernate3.SessionHolder@1fee2db] for key [org.hibernate.impl.SessionFactoryImpl@1fe3238] bound to thread [http-8088-Processor25]


03:35:16,593 DEBUG HibernateTransactionManager:390 - Found thread-bound Session [org.hibernate.impl.SessionImpl@dfbabd] for Hibernate transaction


03:35:16,593 DEBUG TransactionSynchronizationManager:139 - Retrieved value [org.springframework.jdbc.datasource.ConnectionHolder@1672c01] for key [org.apache.commons.dbcp.BasicDataSource@54cbb9] bound to thread [http-8088-Processor25]


03:35:16,593 DEBUG HibernateTransactionManager:292 - Using transaction object [org.springframework.orm.hibernate3.HibernateTransactionManager$HibernateTransactionObject@5ec940]


03:35:16,593 DEBUG HibernateTransactionManager:358 -

Suspending current transaction, creating new transaction with name [com.hbs.eventlog.EventLogService.eventLog]

03:35:16,593 DEBUG TransactionSynchronizationManager:272 - Clearing transaction synchronization


03:35:16,593 DEBUG TransactionSynchronizationManager:190 - Removed value [org.springframework.orm.hibernate3.SessionHolder@1fee2db] for key [org.hibernate.impl.SessionFactoryImpl@1fe3238] from thread [http-8088-Processor25]


03:35:16,609 DEBUG TransactionSynchronizationManager:190 - Removed value [org.springframework.jdbc.datasource.ConnectionHolder@1672c01] for key [org.apache.commons.dbcp.BasicDataSource@54cbb9] from thread [http-8088-Processor25]


03:35:16,609 DEBUG HibernateTransactionManager:428 -

Opened new Session [org.hibernate.impl.SessionImpl@eeb406] for Hibernate transaction

03:35:16,609 DEBUG HibernateTransactionManager:440 - Preparing JDBC Connection of Hibernate Session [org.hibernate.impl.SessionImpl@eeb406]


03:35:16,609 DEBUG HibernateTransactionManager:510 - Exposing Hibernate transaction as JDBC transaction [org.apache.commons.dbcp.PoolableConnection@8543aa]


03:35:16,609 DEBUG TransactionSynchronizationManager:166 - Bound value [org.springframework.jdbc.datasource.ConnectionHolder@16d03ba] for key [org.apache.commons.dbcp.BasicDataSource@54cbb9] to thread [http-8088-Processor25]


03:35:16,609 DEBUG TransactionSynchronizationManager:166 - Bound value [org.springframework.orm.hibernate3.SessionHolder@fbfa2] for key [org.hibernate.impl.SessionFactoryImpl@1fe3238] to thread [http-8088-Processor25]


03:35:16,609 DEBUG TransactionSynchronizationManager:219 - Initializing transaction synchronization


03:35:16,609 DEBUG TransactionInterceptor:275 - Getting transaction for [com.hbs.eventlog.EventLogService.eventLog]


03:35:16,625 DEBUG TransactionSynchronizationManager:139 - Retrieved value [org.springframework.orm.hibernate3.SessionHolder@fbfa2] for key [org.hibernate.impl.SessionFactoryImpl@1fe3238] bound to thread [http-8088-Processor25]


03:35:16,625 DEBUG TransactionSynchronizationManager:139 - Retrieved value [org.springframework.orm.hibernate3.SessionHolder@fbfa2] for key [org.hibernate.impl.SessionFactoryImpl@1fe3238] bound to thread [http-8088-Processor25]


03:35:16,625 DEBUG HibernateTemplate:354 - Found thread-bound Session for HibernateTemplate


03:35:16,625 DEBUG SQL:393 - select hotel0_.HOTEL_ID as HOTEL1_3_0_, hotel0_.HOTEL_NAME as HOTEL2_3_0_, hotel0_.DESCRIPTION as DESCRIPT3_3_0_, hotel0_.CHARACTERISTIC as CHARACTE4_3_0_, hotel0_.STAR_CLASS as STAR5_3_0_, hotel0_.ESTABLISH_DATE as ESTABLISH6_3_0_, hotel0_.BUSINESS_LICENSE as BUSINESS7_3_0_, hotel0_.LEGAL_PERSON as LEGAL8_3_0_, hotel0_.ADDRESS as ADDRESS3_0_, hotel0_.PHONE as PHONE3_0_, hotel0_.EMAIL as EMAIL3_0_, hotel0_.INTERNET_ADDRESS as INTERNET12_3_0_, hotel0_.HOTEL_LOG as HOTEL13_3_0_, hotel0_.COPYRIGHT as COPYRIGHT3_0_, hotel0_.NOTES as NOTES3_0_, hotel0_.CUR_ORDERFORM_ID as CUR16_3_0_ from hbs.hbs_hotel hotel0_ where hotel0_.HOTEL_ID=?


03:35:16,625 DEBUG HibernateTemplate:378 - Not closing pre-bound Hibernate Session after HibernateTemplate


03:35:16,625 DEBUG TransactionSynchronizationManager:139 - Retrieved value [org.springframework.orm.hibernate3.SessionHolder@fbfa2] for key [org.hibernate.impl.SessionFactoryImpl@1fe3238] bound to thread [http-8088-Processor25]


03:35:16,625 DEBUG TransactionSynchronizationManager:139 - Retrieved value [org.springframework.orm.hibernate3.SessionHolder@fbfa2] for key [org.hibernate.impl.SessionFactoryImpl@1fe3238] bound to thread [http-8088-Processor25]


03:35:16,625 DEBUG HibernateTemplate:354 - Found thread-bound Session for HibernateTemplate


03:35:16,625 DEBUG SQL:393 - update hbs.hbs_hotel set HOTEL_NAME=?, DESCRIPTION=?, CHARACTERISTIC=?, STAR_CLASS=?, ESTABLISH_DATE=?, BUSINESS_LICENSE=?, LEGAL_PERSON=?, ADDRESS=?, PHONE=?, EMAIL=?, INTERNET_ADDRESS=?, HOTEL_LOG=?, COPYRIGHT=?, NOTES=?, CUR_ORDERFORM_ID=? where HOTEL_ID=?


03:35:16,640 DEBUG HibernateTemplate:378 - Not closing pre-bound Hibernate Session after HibernateTemplate


03:35:16,640 DEBUG TransactionInterceptor:305 - Completing transaction for [com.hbs.eventlog.EventLogService.eventLog]


03:35:16,640 DEBUG HibernateTransactionManager:776 - Triggering beforeCommit synchronization


03:35:16,640 DEBUG HibernateTransactionManager:789 - Triggering beforeCompletion synchronization


03:35:16,640 DEBUG HibernateTransactionManager:609 - Initiating transaction commit


03:35:16,640 DEBUG HibernateTransactionManager:557 -

Committing Hibernate transaction on Session [org.hibernate.impl.SessionImpl@eeb406]

03:35:16,671 DEBUG HibernateTransactionManager:802 - Triggering afterCommit synchronization


03:35:16,671 DEBUG HibernateTransactionManager:818 - Triggering afterCompletion synchronization


03:35:16,671 DEBUG TransactionSynchronizationManager:272 - Clearing transaction synchronization


03:35:16,671 DEBUG TransactionSynchronizationManager:190 - Removed value [org.springframework.orm.hibernate3.SessionHolder@fbfa2] for key [org.hibernate.impl.SessionFactoryImpl@1fe3238] from thread [http-8088-Processor25]


03:35:16,671 DEBUG TransactionSynchronizationManager:190 - Removed value [org.springframework.jdbc.datasource.ConnectionHolder@16d03ba] for key [org.apache.commons.dbcp.BasicDataSource@54cbb9] from thread [http-8088-Processor25]


03:35:16,671 DEBUG HibernateTransactionManager:636 -

Closing Hibernate Session [org.hibernate.impl.SessionImpl@eeb406] after transaction

03:35:16,671 DEBUG SessionFactoryUtils:781 - Closing Hibernate Session


03:35:16,671 DEBUG HibernateTransactionManager:870 - Resuming suspended transaction


03:35:16,671 DEBUG TransactionSynchronizationManager:166 - Bound value [org.springframework.orm.hibernate3.SessionHolder@1fee2db] for key [org.hibernate.impl.SessionFactoryImpl@1fe3238] to thread [http-8088-Processor25]


03:35:16,671 DEBUG TransactionSynchronizationManager:166 - Bound value [org.springframework.jdbc.datasource.ConnectionHolder@1672c01] for key [org.apache.commons.dbcp.BasicDataSource@54cbb9] to thread [http-8088-Processor25]


03:35:16,671 DEBUG TransactionSynchronizationManager:219 - Initializing transaction synchronization


記錄日誌結束

03:35:16,671 DEBUG TransactionInterceptor:320 - Completing transaction for [com.hbs.customer.CustomerService.customerLogin] after exception: com.hbs.common.ResultException: 登陸失敗!用戶名或密碼不正確


03:35:16,671 DEBUG RuleBasedTransactionAttribute:130 - Applying rules to determine whether transaction should rollback on com.hbs.common.ResultException: 登陸失敗!用戶名或密碼不正確


03:35:16,687 DEBUG RuleBasedTransactionAttribute:148 - Winning rollback rule is: RollbackRuleAttribute with pattern [Exception]


03:35:16,687 DEBUG HibernateTransactionManager:789 - Triggering beforeCompletion synchronization


03:35:16,687 DEBUG HibernateTransactionManager:700 - Initiating transaction rollback


03:35:16,687 DEBUG HibernateTransactionManager:576 - Rolling back Hibernate transaction on Session [org.hibernate.impl.SessionImpl@dfbabd]


03:35:16,687 DEBUG HibernateTransactionManager:818 - Triggering afterCompletion synchronization


03:35:16,687 DEBUG TransactionSynchronizationManager:272 - Clearing transaction synchronization


03:35:16,687 DEBUG TransactionSynchronizationManager:190 - Removed value [org.springframework.jdbc.datasource.ConnectionHolder@1672c01] for key [org.apache.commons.dbcp.BasicDataSource@54cbb9] from thread [http-8088-Processor25]


03:35:16,687 DEBUG HibernateTransactionManager:643 - Not closing pre-bound Hibernate Session [org.hibernate.impl.SessionImpl@dfbabd] after transaction


03:35:16,687 WARN ActionMapping:74 - Unable to find 'null' forward.


03:35:16,687 DEBUG TransactionSynchronizationManager:190 - Removed value [org.springframework.orm.hibernate3.SessionHolder@1fee2db] for key [org.hibernate.impl.SessionFactoryImpl@1fe3238] from thread [http-8088-Processor25]


03:35:16,687 DEBUG OpenSessionInViewFilter:221 - Closing single Hibernate Session in OpenSessionInViewFilter


03:35:16,687 DEBUG SessionFactoryUtils:781 - Closing Hibernate Session



從 中能夠看出,log異常攔截器在用戶登陸的事務回滾以前截獲異常,在記錄日誌時,日誌記錄的service方法也在spring的事務管理之下,用戶登陸 的事務尚未結束,根據REQUIRES_NEW特性,spring會新開一個事務,這時原來的數據庫鏈接已經在一個事務中,一個鏈接不可能同時有兩個事 務,因此同時新建立一個session鏈接(雖然我使用了OpenSessionInViewFilter,而且session是單例的),日誌記錄就在 新建的事務和session中進行,完了提交,而且會把新建的session鏈接關閉。


而後繼續進行被中斷的用戶登陸的事務管理操做,因爲拋異常spring將用戶登陸的事務回滾。


這樣可以實現預想的功能,可是若是我去掉指定的REQUIRES_NEW,那麼log記錄的操做會繼續在用戶登陸的事務中進行,最後會被一塊兒回滾。



若是我把事務管理的order設爲2,log攔截器的order設爲1,也就是log攔截器在事務管理攔截器的外面,會在事務管理攔截器先後執行完了再執行log的異常攔截器,打印信息以下:


03:53:46,125 DEBUG OpenSessionInViewFilter:253 - Using SessionFactory 'sessionFactory' for OpenSessionInViewFilter


03:53:46,156 DEBUG OpenSessionInViewFilter:196 - Opening single Hibernate Session in OpenSessionInViewFilter


03:53:46,156 DEBUG SessionFactoryUtils:333 - Opening Hibernate Session


03:53:46,265 DEBUG TransactionSynchronizationManager:166 - Bound value [org.springframework.orm.hibernate3.SessionHolder@889c4e] for key [org.hibernate.impl.SessionFactoryImpl@cdf872] to thread [http-8088-Processor25]


03:53:46,296 INFO ComposableRequestProcessor:144 - Initializing composable request processor for module prefix ''


03:53:46,375 INFO CreateAction:65 - Initialize action of type: org.springframework.web.struts.DelegatingActionProxy


03:53:46,406 INFO JdbcTransactionObjectSupport:60 - JDBC 3.0 Savepoint class is available


03:53:46,406 DEBUG TransactionSynchronizationManager:139 - Retrieved value [org.springframework.orm.hibernate3.SessionHolder@889c4e] for key [org.hibernate.impl.SessionFactoryImpl@cdf872] bound to thread [http-8088-Processor25]


03:53:46,406 DEBUG HibernateTransactionManager:390 - Found thread-bound Session [org.hibernate.impl.SessionImpl@c21d01] for Hibernate transaction


03:53:46,406 DEBUG HibernateTransactionManager:292 - Using transaction object [org.springframework.orm.hibernate3.HibernateTransactionManager$HibernateTransactionObject@1fe6783]


03:53:46,406 DEBUG HibernateTransactionManager:320 - Creating new transaction with name [com.hbs.customer.CustomerService.customerLogin]


03:53:46,421 DEBUG HibernateTransactionManager:440 - Preparing JDBC Connection of Hibernate Session [org.hibernate.impl.SessionImpl@c21d01]


03:53:46,468 DEBUG HibernateTransactionManager:510 - Exposing Hibernate transaction as JDBC transaction [org.apache.commons.dbcp.PoolableConnection@16c02df]


03:53:46,468 DEBUG TransactionSynchronizationManager:166 - Bound value [org.springframework.jdbc.datasource.ConnectionHolder@30803a] for key [org.apache.commons.dbcp.BasicDataSource@54cbb9] to thread [http-8088-Processor25]


03:53:46,468 DEBUG TransactionSynchronizationManager:219 - Initializing transaction synchronization


03:53:46,484 DEBUG TransactionInterceptor:275 - Getting transaction for [com.hbs.customer.CustomerService.customerLogin]


用戶登陸

03:53:46,500 DEBUG TransactionSynchronizationManager:139 - Retrieved value [org.springframework.orm.hibernate3.SessionHolder@889c4e] for key [org.hibernate.impl.SessionFactoryImpl@cdf872] bound to thread [http-8088-Processor25]


03:53:46,500 DEBUG TransactionSynchronizationManager:139 - Retrieved value [org.springframework.orm.hibernate3.SessionHolder@889c4e] for key [org.hibernate.impl.SessionFactoryImpl@cdf872] bound to thread [http-8088-Processor25]


03:53:46,515 DEBUG HibernateTemplate:354 - Found thread-bound Session for HibernateTemplate


03:53:46,531 DEBUG SQL:393 - select this_.CUSTOMER_ID as CUSTOMER1_5_0_, this_.CUSTOMER_GROUP_ID as CUSTOMER2_5_0_, this_.CUSTOMER_PASSWORD as CUSTOMER3_5_0_, this_.CUSTOMER_NAME as CUSTOMER4_5_0_, this_.CUSTOMER_DESCRIPTION as CUSTOMER5_5_0_, this_.CUSTOMER_KIND as CUSTOMER6_5_0_, this_.CUSTOMER_SEX as CUSTOMER7_5_0_, this_.PHONE as PHONE5_0_, this_.MOBILE as MOBILE5_0_, this_.ADDRESS as ADDRESS5_0_, this_.EMAIL as EMAIL5_0_, this_.CONFIRM_TYPE as CONFIRM12_5_0_, this_.CREATE_TIME as CREATE13_5_0_, this_.GROUP_TIME as GROUP14_5_0_, this_.FIRST_TIME as FIRST15_5_0_, this_.LAST_TIME as LAST16_5_0_, this_.LOGIN_COUNT as LOGIN17_5_0_, this_.CREDIT_VALUE as CREDIT18_5_0_, this_.CUMULATE_VALUE as CUMULATE19_5_0_, this_.STATUS as STATUS5_0_, this_.NOTES as NOTES5_0_ from hbs.hbs_customer this_ where this_.CUSTOMER_ID=? and this_.CUSTOMER_PASSWORD=?


03:53:46,593 DEBUG HibernateTemplate:378 - Not closing pre-bound Hibernate Session after HibernateTemplate


03:53:46,593 DEBUG TransactionInterceptor:320 - Completing transaction for [com.hbs.customer.CustomerService.customerLogin] after exception: com.hbs.common.ResultException: 登陸失敗!用戶名或密碼不正確


03:53:46,609 DEBUG RuleBasedTransactionAttribute:130 - Applying rules to determine whether transaction should rollback on com.hbs.common.ResultException: 登陸失敗!用戶名或密碼不正確


03:53:46,609 DEBUG RuleBasedTransactionAttribute:148 - Winning rollback rule is: RollbackRuleAttribute with pattern [Exception]


03:53:46,609 DEBUG HibernateTransactionManager:789 - Triggering beforeCompletion synchronization


03:53:46,609 DEBUG HibernateTransactionManager:700 - Initiating transaction rollback


03:53:46,609 DEBUG HibernateTransactionManager:576 -

Rolling back Hibernate transaction on Session [org.hibernate.impl.SessionImpl@c21d01]

03:53:46,609 DEBUG HibernateTransactionManager:818 - Triggering afterCompletion synchronization


03:53:46,609 DEBUG TransactionSynchronizationManager:272 - Clearing transaction synchronization


03:53:46,609 DEBUG TransactionSynchronizationManager:190 - Removed value [org.springframework.jdbc.datasource.ConnectionHolder@30803a] for key [org.apache.commons.dbcp.BasicDataSource@54cbb9] from thread [http-8088-Processor25]


03:53:46,625 DEBUG HibernateTransactionManager:643 - Not closing pre-bound Hibernate Session [org.hibernate.impl.SessionImpl@c21d01] after transaction


記錄日誌開始

03:53:46,640 DEBUG TransactionSynchronizationManager:139 - Retrieved value [org.springframework.orm.hibernate3.SessionHolder@889c4e] for key [org.hibernate.impl.SessionFactoryImpl@cdf872] bound to thread [http-8088-Processor25]


03:53:46,640 DEBUG HibernateTransactionManager:390 - Found thread-bound Session [org.hibernate.impl.SessionImpl@c21d01] for Hibernate transaction


03:53:46,640 DEBUG HibernateTransactionManager:292 - Using transaction object [org.springframework.orm.hibernate3.HibernateTransactionManager$HibernateTransactionObject@1f68336]


03:53:46,640 DEBUG HibernateTransactionManager:320 -

Creating new transaction with name [com.hbs.eventlog.EventLogService.eventLog]

03:53:46,640 DEBUG HibernateTransactionManager:440 - Preparing JDBC Connection of Hibernate Session [org.hibernate.impl.SessionImpl@c21d01]


03:53:46,640 DEBUG HibernateTransactionManager:510 - Exposing Hibernate transaction as JDBC transaction [org.apache.commons.dbcp.PoolableConnection@16c02df]


03:53:46,640 DEBUG TransactionSynchronizationManager:166 - Bound value [org.springframework.jdbc.datasource.ConnectionHolder@1205042] for key [org.apache.commons.dbcp.BasicDataSource@54cbb9] to thread [http-8088-Processor25]


03:53:46,656 DEBUG TransactionSynchronizationManager:219 - Initializing transaction synchronization


03:53:46,656 DEBUG TransactionInterceptor:275 - Getting transaction for [com.hbs.eventlog.EventLogService.eventLog]


03:53:46,656 DEBUG TransactionSynchronizationManager:139 - Retrieved value [org.springframework.orm.hibernate3.SessionHolder@889c4e] for key [org.hibernate.impl.SessionFactoryImpl@cdf872] bound to thread [http-8088-Processor25]


03:53:46,656 DEBUG TransactionSynchronizationManager:139 - Retrieved value [org.springframework.orm.hibernate3.SessionHolder@889c4e] for key [org.hibernate.impl.SessionFactoryImpl@cdf872] bound to thread [http-8088-Processor25]


03:53:46,656 DEBUG HibernateTemplate:354 - Found thread-bound Session for HibernateTemplate


03:53:46,656 DEBUG SQL:393 - select hotel0_.HOTEL_ID as HOTEL1_3_0_, hotel0_.HOTEL_NAME as HOTEL2_3_0_, hotel0_.DESCRIPTION as DESCRIPT3_3_0_, hotel0_.CHARACTERISTIC as CHARACTE4_3_0_, hotel0_.STAR_CLASS as STAR5_3_0_, hotel0_.ESTABLISH_DATE as ESTABLISH6_3_0_, hotel0_.BUSINESS_LICENSE as BUSINESS7_3_0_, hotel0_.LEGAL_PERSON as LEGAL8_3_0_, hotel0_.ADDRESS as ADDRESS3_0_, hotel0_.PHONE as PHONE3_0_, hotel0_.EMAIL as EMAIL3_0_, hotel0_.INTERNET_ADDRESS as INTERNET12_3_0_, hotel0_.HOTEL_LOG as HOTEL13_3_0_, hotel0_.COPYRIGHT as COPYRIGHT3_0_, hotel0_.NOTES as NOTES3_0_, hotel0_.CUR_ORDERFORM_ID as CUR16_3_0_ from hbs.hbs_hotel hotel0_ where hotel0_.HOTEL_ID=?


03:53:46,718 DEBUG HibernateTemplate:378 - Not closing pre-bound Hibernate Session after HibernateTemplate


03:53:46,734 DEBUG TransactionSynchronizationManager:139 - Retrieved value [org.springframework.orm.hibernate3.SessionHolder@889c4e] for key [org.hibernate.impl.SessionFactoryImpl@cdf872] bound to thread [http-8088-Processor25]


03:53:46,734 DEBUG TransactionSynchronizationManager:139 - Retrieved value [org.springframework.orm.hibernate3.SessionHolder@889c4e] for key [org.hibernate.impl.SessionFactoryImpl@cdf872] bound to thread [http-8088-Processor25]


03:53:46,734 DEBUG HibernateTemplate:354 - Found thread-bound Session for HibernateTemplate


03:53:46,812 DEBUG SQL:393 - update hbs.hbs_hotel set HOTEL_NAME=?, DESCRIPTION=?, CHARACTERISTIC=?, STAR_CLASS=?, ESTABLISH_DATE=?, BUSINESS_LICENSE=?, LEGAL_PERSON=?, ADDRESS=?, PHONE=?, EMAIL=?, INTERNET_ADDRESS=?, HOTEL_LOG=?, COPYRIGHT=?, NOTES=?, CUR_ORDERFORM_ID=? where HOTEL_ID=?


03:53:46,812 DEBUG HibernateTemplate:378 - Not closing pre-bound Hibernate Session after HibernateTemplate


03:53:46,812 DEBUG TransactionInterceptor:305 - Completing transaction for [com.hbs.eventlog.EventLogService.eventLog]


03:53:46,812 DEBUG HibernateTransactionManager:776 - Triggering beforeCommit synchronization


03:53:46,812 DEBUG HibernateTransactionManager:789 - Triggering beforeCompletion synchronization


03:53:46,812 DEBUG HibernateTransactionManager:609 - Initiating transaction commit


03:53:46,812 DEBUG HibernateTransactionManager:557 -

Committing Hibernate transaction on Session [org.hibernate.impl.SessionImpl@c21d01]

03:53:46,859 DEBUG HibernateTransactionManager:802 - Triggering afterCommit synchronization


03:53:46,859 DEBUG HibernateTransactionManager:818 - Triggering afterCompletion synchronization


03:53:46,859 DEBUG TransactionSynchronizationManager:272 - Clearing transaction synchronization


03:53:46,859 DEBUG TransactionSynchronizationManager:190 - Removed value [org.springframework.jdbc.datasource.ConnectionHolder@1205042] for key [org.apache.commons.dbcp.BasicDataSource@54cbb9] from thread [http-8088-Processor25]


03:53:46,859 DEBUG HibernateTransactionManager:643 - Not closing pre-bound Hibernate Session [org.hibernate.impl.SessionImpl@c21d01] after transaction


記錄日誌結束


03:53:46,859 WARN ActionMapping:74 - Unable to find 'null' forward.


03:53:46,859 DEBUG TransactionSynchronizationManager:190 - Removed value [org.springframework.orm.hibernate3.SessionHolder@889c4e] for key [org.hibernate.impl.SessionFactoryImpl@cdf872] from thread [http-8088-Processor25]


03:53:46,859 DEBUG OpenSessionInViewFilter:221 - Closing single Hibernate Session in OpenSessionInViewFilter


03:53:46,875 DEBUG SessionFactoryUtils:781 - Closing Hibernate Session



可 以看出,用戶登陸的事務和日誌記錄的事務是先後兩個不相關的事務,而且在日誌記錄事務中並不須要新建session鏈接,而是直接用在 OpenSessionInViewFilter中建立的session。實際上這時也並不須要將propagation設爲REQUIRES_NEW, 使用默認的REQUIRES也照樣可以正常工做。



因此應該將該異常攔截器設在事務管理攔截器的外面,即便用Order接口排在前面。

相關文章
相關標籤/搜索