<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    posts - 30,  comments - 85,  trackbacks - 0

    Spring事務(wù)的學(xué)習(xí)

    ?????? 今天對(duì) spring AOP 事務(wù)有了一個(gè)新的認(rèn)識(shí),所以趕緊把今天的學(xué)習(xí)記下來,希望在今后的學(xué)習(xí)中能夠起到一些作用,也能對(duì)今天的認(rèn)識(shí)做一次總結(jié)。

    1????????? 同事的 spring 分享

    先看一段代碼:
    ???
    Connection conn = Conn.getConnection();
    ??? conn.setAutoCommit(false);
    ??? ……..
    ??? ……...
    ??? conn.rollback();
    ??? conn.commit();


    ???
    數(shù)據(jù)庫的事務(wù)是針對(duì) Connection 的。

    ???
    接著再看一段代碼:( spring 中事務(wù)的一段學(xué)習(xí)代碼,這段代碼是把 spring hibernate 結(jié)合在一起的,增加了理解上的難度,因?yàn)槲业某霭l(fā)點(diǎn)一開始不要 hibernate ,就光用 jdbc 來進(jìn)行數(shù)據(jù)庫事務(wù),但是沒有其他好的代碼,就這樣吧)

    ??? public Long addLineItem(Long orderId, LineItem lineItem){

    ?????? log("OrderListDAOHibernate.addLineItem : Start...");

    ?????? OrderList orderList = (OrderList) getHibernateTemplate().load(OrderList.class, orderId);

    ?????? lineItem.setOrderList(orderList);

    ?????? getHibernateTemplate().saveOrUpdate(lineItem);

    ?????? getHibernateTemplate().saveOrUpdate(orderList);

    ?????? log("OrderListDAOHibernate.addLineItem : Ending...");

    ?????? return lineItem.getId();

    ??? }

    ???
    在這個(gè)代碼的配置文件中,把 addLineItem 做為一個(gè)切入點(diǎn),進(jìn)行事務(wù),也就是說,在 addLineItem 的外面,再包上一層事務(wù)的外殼。

    ???
    但是這個(gè)時(shí)候,問題出來了,事務(wù)是針對(duì) Connection 的,而上面的兩個(gè)連續(xù)的 HibernateTemplate 執(zhí)行的 saveOrUpdate 中的 Connection 必須是一致才能用事務(wù), spring 怎么做到這一點(diǎn)的呢?(這個(gè)問題也就是在找 spring 的事務(wù)例子前,我想的 spring 中用 jdbc 來進(jìn)行事務(wù),怎么樣讓 Connection 保持一致呢?但是沒有 jdbc 的例子,只有整合 hibernate 或者 ibatis 的例子,但是,我想,原理是一樣的吧。)

    ?

    ??? 解決問題的思路: HibernateTemplate 中的 Connection 必定一致。那么就從 HibernateTemplate 入手。

    ??? spring 的源代碼,既然是 Hibernate ,那么,就沒有 Connection 給你看,只有 Session ,由 Session 來管理 Connection ,那么用事務(wù)來控制的話,這個(gè) Session 必定在所有該事務(wù)中是一致的。于是在 HibernateTemplate 中找到:


    protected Session getSession() {

    ?????? if (isAlwaysUseNewSession()) {

    return SessionFactoryUtils.getNewSession(getSessionFactory(), getEntityInterceptor());

    ?????? }

    ?????? else if (!isAllowCreate()) {

    return SessionFactoryUtils.getSession(getSessionFactory(), false);

    ?????? }

    ?????? else {

    return SessionFactoryUtils.getSession(

    ????????????????? getSessionFactory(), getEntityInterceptor(), getJdbcExceptionTranslator());

    ?????? }

    ??? }

    ?

    看來在 SessionFactoryUtils 里面,接著在 SessionFactoryUtils.getSession 中找:

    ?

    這個(gè)方法太長(zhǎng)了,太復(fù)雜了,從簡(jiǎn),發(fā)現(xiàn)了非常關(guān)鍵的一點(diǎn):

    ?

    SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager.getResource(sessionFactory);

    ?

    假如 sessionHolder 不等于空,說明,在事務(wù)中有這樣一個(gè)還沒有 commit session ,那么就返回這個(gè) session ,假如等于空,新建一個(gè) session ,并且在事務(wù)里加入這個(gè) session 。這段代碼的意思大概是這樣,太繁雜了,只能猜,也肯定是如此。

    ?

    再看 getHibernateTemplate() 方法來自繼承 HibernateDaoSupport ,看了電子書《 spring-reference 》的第九章“ Dao 支持”, Dao 的支持類可以有好多,如: JdbcDaoSupport HibernateDaoSupport JdoDaoSupport 等等。

    ?

    既然前面一開始就是從 jdbc spring 事務(wù)控制引起的,那么看到了同樣的 HibernateDaoSupport---JdbcDaoSupport ,那么 JdbcDaoSupport 也應(yīng)該有 getJdbcTemplate() 這個(gè)方法,并且返回 JdbcTemplate 這個(gè)類。

    ?

    果然如此。

    ?

    于是剖析 JdbcTemplate 是不是和 HibernateTemplate 一樣。果然一樣。

    ?

    注意到:

    Connection con = DataSourceUtils.getConnection(getDataSource());

    ?

    Connection 是從 DataSourceUtils.getConnection() 來的,繼續(xù)跟蹤 DataSourceUtils.getConnection()

    ?

    找到:

    ConnectionHolder conHolder = (ConnectionHolder) TransactionSynchronizationManager.getResource(dataSource);

    ?

    Hibernate 中的一模一樣,因?yàn)闆]有了 session 的封裝,條理在 jdbc 中更加清晰了。

    ?

    至此, spring 的事務(wù)控制 已經(jīng)全部搞定。

    2????????? Spring 事務(wù)管理的配置

    看了上面同事學(xué)習(xí) spring 的筆記后自己也覺得有新的理解,從什么地方說起呢?就從 spring 的事務(wù)配置說起吧。那么我們看看 contextConfig.xml 吧。

    <bean id="sessionFactory" class="org.springframework.orm.hibernate.LocalSessionFactoryBean">

    ?????? <property name="dataSource">

    ?????????? <ref bean="dataSource" />

    ?????? </property>

    ?????? <property name="mappingResources">

    ?????????? <list>

    ????????????? <value>mf/org/user/User.hbm.xml</value>

    ?????????? </list>

    ?????? </property>

    </bean>

    <bean id="transactionManager" class="org.springframework.orm.hibernate.HibernateTransactionManager">

    ?????? <property name="sessionFactory">

    ?????????? <ref local="sessionFactory" />

    ?????? </property>

    ??? </bean>

    <bean id="txProxyTemplate" abstract="true" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">

    ?????? <property name="transactionManager">

    ?????????? <ref bean="transactionManager" />

    ?????? </property>

    ?????? <property name="transactionAttributes">

    ?????????? <props>

    <prop key="save*">PROPAGATION_REQUIRED,-Exception</prop>

    <prop key="remove*">PROPAGATION_REQUIRED,-Exception </prop>

    <prop key="update*">PROPAGATION_REQUIRED,-Exception </prop>

    <prop key="incress*">PROPAGATION_REQUIRED,-Exception </prop>

    <prop key="*">PROPAGATION_REQUIRED,readOnly</prop>

    ?????????? </props>

    ?????? </property>

    ??? </bean>

    <bean id="userManager" parent="txProxyTemplate">

    ?????? <property name="target" ref="userManagerTarget" />

    </bean>

    <bean id="userManagerTarget"

    class=" mf.org.hb.user.service.impl.UserManagerImpl">

    ?????? <property name="userDAO" ref="userDAO" />

    </bean>

    <bean id="userDAO" class="mf.org.hb.user.dao.hibernate.UserDAOHibernate">

    ?????? <property name="sessionFactory" ref="sessionFactory" />

    </bean>

    ??? 以上就是一個(gè)完整的 spring 配置,是不是很熟悉呢,這里是用的 Appfuse 的框架,呵呵。有那么點(diǎn)味道吧。

    ??? 首先我們看看

    <bean id="transactionManager" class="org.springframework.orm.hibernate.HibernateTransactionManager">

    ?????? <property name="sessionFactory">

    ?????????? <ref local="sessionFactory" />

    ?????? </property>

    </bean>

    ??? 這一個(gè) bean spring 為我們注入了什么呢?事務(wù),對(duì)!我們把 hibernate 的事務(wù)注入到了 spring IOC 容器之中了。然后我們?cè)倏纯矗?/span>

    ??? <bean id="txProxyTemplate" abstract="true" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">

    ?????? <property name="transactionManager">

    ?????????? <ref bean="transactionManager" />

    ?????? </property>

    ?????? <property name="transactionAttributes">

    ?????????? <props>

    <prop key="save*">PROPAGATION_REQUIRED,-Exception</prop>

    <prop key="remove*">PROPAGATION_REQUIRED,-Exception </prop>

    <prop key="update*">PROPAGATION_REQUIRED,-Exception </prop>

    <prop key="incress*">PROPAGATION_REQUIRED,-Exception </prop>

    <prop key="*">PROPAGATION_REQUIRED,readOnly</prop>

    ?????????? </props>

    ?????? </property>

    </bean>

    ??? 這個(gè) bean 又是讓 spring 為我們注入了了什么呢?事務(wù)代理,對(duì)了!我們把事務(wù)的代理交給一個(gè) txProxyTemplate 的去做了,這樣的好處我待會(huì)再說,現(xiàn)在我們看看下面的一些配置信息。

    <prop key="save*">PROPAGATION_REQUIRED,-Exception</prop>

    <prop key="remove*">PROPAGATION_REQUIRED,-Exception </prop>

    <prop key="update*">PROPAGATION_REQUIRED,-Exception </prop>

    <prop key="incress*">PROPAGATION_REQUIRED,-Exception </prop>

    <prop key="*">PROPAGATION_REQUIRED,readOnly</prop>

    這里就是事務(wù)處理時(shí)如果遇到異常信息,或者其他的原因時(shí)我們要求 spring 把當(dāng)前的事務(wù)回滾了,這樣才能不至于在數(shù)據(jù)庫中產(chǎn)生垃圾啊。我們規(guī)定所有的 save,remove,update,incress 這樣的方法開頭的在出現(xiàn)一些問題后把事務(wù)給回滾了,看看我們寫的: PROPAGATION_REQUIRED,-Exception

    有人就會(huì)說 PROPAGATION_REQUIRED 就可以回滾事務(wù)啊,為什么加上 ,-Exception 呢?其實(shí)我以前也時(shí)這樣想的,但這是不完全正確的,當(dāng)然我們?cè)谔幚硪粋€(gè)事務(wù)時(shí)只要有一個(gè) PROPAGATION_REQUIRED 就可以了,但是當(dāng)我們的業(yè)務(wù)邏輯中要求我們?cè)谝粋€(gè)事務(wù)代理中開啟兩個(gè)事務(wù),這兩個(gè)事務(wù)表面上沒有聯(lián)系,但是實(shí)際中又有很多聯(lián)系的,比如我們上傳附件和提交文檔,這樣兩個(gè)操作我們可以分開,因?yàn)樗麄儾皇峭粋€(gè)表里插入數(shù)據(jù),我們又不希望這兩個(gè)操作寫在一個(gè) service 里,這樣我們要是有一個(gè)業(yè)務(wù)只要上傳附件呢?那樣我們是不是又要再寫一個(gè)方法啊!所以在開啟兩個(gè)事務(wù)時(shí)如果有一個(gè)拋出異常了,我們就要把上一個(gè)提交的事務(wù)回滾了,這樣做我們就要用的 -Exception 了,這樣就完全滿足我們的要求了,我也試過如果我寫的是 PROPAGATION_REQUIRED,-SQLException 時(shí),這樣我們只會(huì)在出現(xiàn) SQLException 時(shí)事務(wù)回顧,出現(xiàn)其他的異常事務(wù)就不回滾了,好在 spring 可以讓我們寫如異常的基類就可以做到捕獲任何異常,這樣我們就寫 -Exception 好了。特殊情況在特殊處理吧。通用情況下我們還是這樣的。

    我們?cè)倏纯矗?/span>

    <bean id="userManager" parent="txProxyTemplate">

    ?????? <property name="target" ref="userManagerTarget" />

    </bean>

    <bean id="userManagerTarget"

    class="mf.org.hb.user.service.impl.UserManagerImpl">

    ?????? <property name="userDAO" ref="userDAO" />

    </bean>

    <bean id="userDAO" class="mf.org.hb.user.dao.hibernate.UserDAOHibernate">

    ?????? <property name="sessionFactory" ref="sessionFactory" />

    </bean>

    ??? 當(dāng)然我們也可以寫成:

    <bean id="userManager" parent="txProxyTemplate">

    ?????? <property name="target">

    ?????????? <bean class="mf.org.hb.user.service.impl.UserManagerImpl">

    ????????????? <property name="userDAO">

    ????????????????? <ref bean="userDao"/>

    ????????????? </property>

    ?????????? </bean>

    ?????? </property>

    </bean>

    <bean id="userDAO" class="mf.org.hb.user.dao.hibernate.UserDAOHibernate">

    ?????? <property name="sessionFactory" ref="sessionFactory" />

    </bean>

    ?

    這下我們解除以前的疑惑, parent="txProxyTemplate" 知道我們?yōu)槭裁丛谏厦嫦葘懥?/span> txProxyTemplate bean 了吧,這樣我們就沒有必要再寫一編了。是不是很方便? spring 的這些技巧還不只這些呢。這樣我們就可以輕松利用以上這三個(gè)注入的類去做我們的邏輯了。

    Spring 就是要我們注入實(shí)現(xiàn)類,然后使用接口操作,這樣耦合性就不是那么強(qiáng)了,這也體現(xiàn)了 Spring 的工廠模式。而 AOP manager 又象我們熟知的代理模式吧 !

    3????????? 注意要點(diǎn)

    在寫配置的時(shí)候注意各個(gè) Manager DAO 之間的關(guān)系,以及 <ref= ”” > 之間的關(guān)系,清晰里面的關(guān)系才能更好的配置。

    posted on 2006-09-15 15:30 安文豪 閱讀(6791) 評(píng)論(8)  編輯  收藏

    FeedBack:
    # re: Spring事務(wù)的學(xué)習(xí)
    2006-09-16 00:29 | 冉翔
    相當(dāng)?shù)?錯(cuò)  回復(fù)  更多評(píng)論
      
    # re: Spring事務(wù)的學(xué)習(xí)
    2006-09-17 13:17 | Supergoal
    JDK 1.5已經(jīng)發(fā)布一年半了,為什么還不在Spirng中使用基本Annotation的聲明性事務(wù)管理呢。  回復(fù)  更多評(píng)論
      
    # re: Spring事務(wù)的學(xué)習(xí)
    2006-09-29 00:25 | 山風(fēng)小子
    受益匪淺!  回復(fù)  更多評(píng)論
      
    # re: Spring事務(wù)的學(xué)習(xí)
    2007-02-07 09:19 | 花生米
    寫的不錯(cuò)
    最近正在搞這個(gè),很有幫助,多謝!  回復(fù)  更多評(píng)論
      
    # re: Spring事務(wù)的學(xué)習(xí)
    2007-06-19 11:18 | chenshan
    非常感謝你,寫得太好了.解決了我的疑惑....  回復(fù)  更多評(píng)論
      
    # re: Spring事務(wù)的學(xué)習(xí)
    2008-04-19 14:02 | dolphin013
    這篇文章太好了,解決了我的問題  回復(fù)  更多評(píng)論
      
    # re: Spring事務(wù)的學(xué)習(xí)[未登錄]
    2008-04-25 11:57 | 學(xué)習(xí)者
    如果事務(wù)管理多個(gè)操作該雜做  回復(fù)  更多評(píng)論
      
    # re: Spring事務(wù)的學(xué)習(xí)
    2008-07-18 11:28 | pengpeng
    問:在外面getbean的時(shí)候是使用userManager還是useruserManagerTarget
    請(qǐng)回復(fù):yuequan08@126.com  回復(fù)  更多評(píng)論
      

    只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


    網(wǎng)站導(dǎo)航:
     

    <2006年9月>
    272829303112
    3456789
    10111213141516
    17181920212223
    24252627282930
    1234567

    常用鏈接

    留言簿(6)

    隨筆檔案(28)

    文章分類(3)

    文章檔案(4)

    最新隨筆

    搜索

    •  

    積分與排名

    • 積分 - 86494
    • 排名 - 666

    最新評(píng)論

    閱讀排行榜

    評(píng)論排行榜

    主站蜘蛛池模板: 免费少妇a级毛片人成网| 亚洲国产日韩在线成人蜜芽| 99亚偷拍自图区亚洲| 99麻豆久久久国产精品免费 | 无码毛片一区二区三区视频免费播放 | 亚洲av无码成人影院一区| 免费无码一区二区三区| 亚洲人成无码网站久久99热国产| 中文字幕亚洲综合久久综合| 免费91麻豆精品国产自产在线观看| 国产一级淫片视频免费看| ass亚洲**毛茸茸pics| 午夜免费啪视频在线观看| 久久久久亚洲精品男人的天堂| 亚洲色成人四虎在线观看| 久久久精品2019免费观看| 亚洲理论电影在线观看| 免费无码午夜福利片69| 国产午夜免费福利红片| 国产 亚洲 中文在线 字幕| 免费视频爱爱太爽了| 亚洲视频在线免费观看| 热99RE久久精品这里都是精品免费| 亚洲国产av无码精品| 色噜噜噜噜亚洲第一| 成人A级毛片免费观看AV网站| 久久综合亚洲色HEZYO社区| 日韩人妻一区二区三区免费| 亚洲国产精品成人精品无码区在线| 一级做a爰片久久毛片免费陪 | 亚洲国产av玩弄放荡人妇 | 亚洲精品午夜国产va久久| ww4545四虎永久免费地址| 亚洲尹人香蕉网在线视颅| 日本免费中文字幕| 久久精品亚洲综合一品| 国产麻豆一精品一AV一免费| 国产亚洲精久久久久久无码| 成人毛片100免费观看| 伊人久久亚洲综合| 中文字幕成人免费高清在线|