1. 程式人生 > >spring 註解 事務和宣告式事務共存的情況下如何決定先後順序

spring 註解 事務和宣告式事務共存的情況下如何決定先後順序

首先先看配置檔案:

[html] view plain copy print?
  1. <!– hibernate –>
  2.     <beanid=“sessionFactory”
  3.         class=“org.springframework.orm.hibernate3.LocalSessionFactoryBean”>
  4.         <propertyname=“dataSource”ref=“dataSource”/>
  5.         <propertyname=“hibernateProperties”>
  6.             <props>
  7.                 <propkey=“hibernate.hbm2ddl.auto”>update</prop>
  8.                 <propkey=“hibernate.show_sql”>true</prop>
  9.                 <propkey=“hibernate.format_sql”>true</prop>
  10.                 <propkey=“connection.autoReconnect”>true</prop>
  11.                 <
    propkey=“connection.autoReconnectForPools”>true</prop>
  12.                 <propkey=“connection.is-connection-validation-required”>true</prop>
  13.                 <propkey=“hibernate.dialect”>org.hibernate.dialect.MySQLDialect</prop>
  14.             </props>
  15.         </property>
  16.         <propertyname=“mappingDirectoryLocations”>
  17.             <list>
  18.                 <value>classpath*:*oddtech/bean</value>
  19.             </list>
  20.         </property>
  21.     </bean>
  22.     <!– 事務管理 –>
  23.     <beanid=“txManager”
  24.         class=“org.springframework.orm.hibernate3.HibernateTransactionManager”>
  25.         <propertyname=“sessionFactory”ref=“sessionFactory”/>
  26.     </bean>
  27.     <!– 註解式事務的支援 –>
  28.     <tx:annotation-driventransaction-manager=“txManager”order=“0”/>
  29.     <!– 服務事務註冊切面 –>
  30.     <aop:config>
  31.         <aop:pointcutexpression=“execution(* oddtech.service.impl.*.*(..))”
  32.             id=“txPoint”/>
  33.         <aop:advisoradvice-ref=“txAdvice”pointcut-ref=“txPoint”order=“1”/>
  34.     </aop:config>
  35.     <tx:advicetransaction-manager=“txManager”id=“txAdvice”>
  36.         <tx:attributes>
  37.             <tx:methodname=“find*”propagation=“REQUIRED”read-only=“true”
  38.                 rollback-for=“Exception”/>
  39.             <tx:methodname=“select*”propagation=“REQUIRED”read-only=“true”
  40.                 rollback-for=“Exception”/>
  41.             <tx:methodname=“insert*”propagation=“REQUIRED”
  42.                 rollback-for=“Exception”/>
  43.             <tx:methodname=“delete*”propagation=“REQUIRED”
  44.                 rollback-for=“Exception”/>
  45.             <tx:methodname=“update*”propagation=“REQUIRED”
  46.                 rollback-for=“Exception”/>
  47.             <tx:methodname=“modify*”propagation=“REQUIRED”
  48.                 rollback-for=“Exception”/>
  49.             <tx:methodname=“*”read-only=“true”
  50.                 rollback-for=“Exception”/>
  51.         </tx:attributes>
  52.     </tx:advice>
<!-- hibernate -->
    <bean id="sessionFactory"
        class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.hbm2ddl.auto">update</prop>
                <prop key="hibernate.show_sql">true</prop>
                <prop key="hibernate.format_sql">true</prop>
                <prop key="connection.autoReconnect">true</prop>
                <prop key="connection.autoReconnectForPools">true</prop>
                <prop key="connection.is-connection-validation-required">true</prop>
                <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
            </props>
        </property>
        <property name="mappingDirectoryLocations">
            <list>
                <value>classpath*:*oddtech/bean</value>
            </list>
        </property>
    </bean>

    <!-- 事務管理 -->
    <bean id="txManager"
        class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory" />
    </bean>
    <!-- 註解式事務的支援 -->
    <tx:annotation-driven transaction-manager="txManager"  order="0"/>
    <!-- 服務事務註冊切面 -->
    <aop:config >
        <aop:pointcut expression="execution(* oddtech.service.impl.*.*(..))"
            id="txPoint"  />
        <aop:advisor advice-ref="txAdvice" pointcut-ref="txPoint"  order="1"/>
    </aop:config>




    <tx:advice transaction-manager="txManager" id="txAdvice">
        <tx:attributes >
            <tx:method name="find*" propagation="REQUIRED" read-only="true" 
                rollback-for="Exception" />
            <tx:method name="select*" propagation="REQUIRED" read-only="true"
                rollback-for="Exception" />
            <tx:method name="insert*" propagation="REQUIRED"  
                rollback-for="Exception" />
            <tx:method name="delete*" propagation="REQUIRED"
                rollback-for="Exception" />
            <tx:method name="update*" propagation="REQUIRED" 
                rollback-for="Exception" />
            <tx:method name="modify*" propagation="REQUIRED"
                rollback-for="Exception" />
            <tx:method name="*" read-only="true"
                rollback-for="Exception" />
        </tx:attributes>
    </tx:advice>

當在oddtech.service.impl包下某個類(Test)某個方法(insert)使用了@Transactional,相當於在執行new Test().insert() 方法執行2次AOP切面。那麼我們需要通過order 屬性去定義AOP切面的先後執行順序。 order越小,在AOP的chain 中越靠前,越先執行。(chain模式)


所以 我們需要在<tx:annotation-driven transaction-manager=”txManager”  order=”0”/>中加入order屬性為0,<aop:advisor advice-ref=”txAdvice” pointcut-ref=”txPoint”  order=”1”/>加入order 屬性為1.那麼他們兩個的執行順序如下:

。這樣就屬於事務巢狀

那麼我們再看上邊說的例子:當在oddtech.service.impl包下某個類(Test)某個方法(insert)使用了@Transactional,那麼我們想讓insert 方法只讀,read-only=true,那麼我們需要這樣去定義:@Transactional(readOnly = true,propagation=Propagation.REQUIRED),為什麼呢?

在宣告事務中,我們對insert 的事務傳播級別定義為:REQUIRED,關於事務傳播級別,請參照http://blog.csdn.net/feng27156/article/details/8534609,那麼在註解事務中我們定義REQUIRED 的事務。宣告事務在使用註解定義的事務級別。

除非在特殊的情況下,註解事務不要和宣告事務有衝突。宣告事務定義的是統一的規則,如果你想讓某一個方法有特殊的事務傳播機制的話,那麼不要和統一的規則有衝突。

<tx:method name=”*” read-only=”true” rollback-for=”Exception” />

按照規則,定義一個test方法,加入:@Transactional定義。則test 方法為read-only=false,propagation=REQUIRED。這是預設的。統一規則<tx:method name=”*” read-only=”true” rollback-for=”Exception” />不會對test方法的註解事務衝突。