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

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

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

    posts - 193,  comments - 520,  trackbacks - 0
    問(wèn)題背景:我們是一家工作流公司,客戶(hù)采購(gòu)我們的產(chǎn)品后,將其嵌入其項(xiàng)目中。我們的工作流采用的是   spring+hibernate的方式,客戶(hù)項(xiàng)目則是jdbc直接進(jìn)行數(shù)據(jù)庫(kù)操作。
    問(wèn)題:客戶(hù)在其數(shù)據(jù)庫(kù)操作過(guò)程中需要調(diào)用我們的工作流接口,這樣就需要將我們的工作流操作與他們的業(yè)  務(wù)操作置于同一個(gè)事務(wù)中。我們的服務(wù)采用的都是spring的聲明式事務(wù),而客戶(hù)采用的是對(duì)         connection進(jìn)行事務(wù)處理。如何保證事務(wù)的一致性?
    想到的解決方案一:使用jta事務(wù),用tomcat+jotm提供事務(wù)管理器。為什么一開(kāi)始就想到要使用jta事務(wù)??實(shí)際上我們和客戶(hù)都是使用的同一個(gè)數(shù)據(jù)庫(kù),為了方便,各自使用了不同的數(shù)據(jù)庫(kù)連接方式,使用jta的話確實(shí)有bt的意思在里面。但是事實(shí)上是我們的第一反應(yīng)都是jta。最后沒(méi)有采用該方法的原因也很簡(jiǎn)單:我沒(méi)有將jotm配置成功!汗一個(gè)。
    想到的解決方案二:將客戶(hù)的這些特定代碼用spring管理起來(lái)。因?yàn)橐薷目蛻?hù)部分代碼,這個(gè)方案遭到了客戶(hù)的強(qiáng)烈反對(duì)。于是放棄。
    想到的解決方案三:客戶(hù)數(shù)據(jù)庫(kù)操作與我們的服務(wù)使用同一個(gè)數(shù)據(jù)庫(kù)連接。然后編程處理事務(wù)。存在兩種方式:一種是把客戶(hù)的連接傳給我們,另一種則是把我們的連接傳給客戶(hù)。第一種方式對(duì)我們的影響太大,所以最后決定采用后一種方式:從hibernate session中獲取connection然后傳遞給客戶(hù)。接下來(lái)查看一下HibernateTemplate的execute()方法,思路就很簡(jiǎn)單了:獲取定義的sessionFactory-->創(chuàng)建一個(gè)新的session并打開(kāi)-->將session與當(dāng)前線程綁定-->給客戶(hù)代碼返回connection-->打開(kāi)事務(wù)-->客戶(hù)使用我們傳遞的connection進(jìn)行數(shù)據(jù)庫(kù)操作-->我們不帶聲明事務(wù)的服務(wù)操作-->提交事務(wù)-->解除綁定。
    實(shí)際要注意的地方是:1、將session與當(dāng)前線程綁定使用的TransactionSynchronizationManager.bindResource()方法,這樣在HibernateTemplate里才能找到session;
                        2、我們的服務(wù)一定要把聲明式事務(wù)徹底干掉,否則會(huì)有commit;
                        3、我們服務(wù)調(diào)用完畢后一定要flush session,否則客戶(hù)代碼不會(huì)感知數(shù)據(jù)庫(kù)里的數(shù)據(jù)變化。
    最終解決:使用了spring里常用的模板和回調(diào)。代碼如下:
    public class TransactionTemplate {

        
    protected final Log logger = LogFactory.getLog(TransactionTemplate.class);

        
    private FlushMode flushMode = FlushMode.ALWAYS;

        
    public Object execute(TransactionCallback callback) {
            
    //首先獲取sessionFactory
            SessionFactory sessionFactory = (SessionFactory) Framework.getEngine()
                    .getContainer().getComponent(
    "sessionFactory");
            
    //創(chuàng)建一個(gè)新的session并打開(kāi)
            logger.debug("Opening single Hibernate Session in TransactionTemplate");
            Session session 
    = getSession(sessionFactory);
            
    //將session與當(dāng)前線程綁定
            TransactionSynchronizationManager.bindResource(sessionFactory, new SessionHolder(session));
            
    //獲取數(shù)據(jù)庫(kù)連接
            Connection conn = session.connection();
            Object result 
    = null;
            Transaction transaction 
    = null;
            
    try {
                
    //開(kāi)始處理事務(wù)
                transaction = session.beginTransaction();
                
    try {
                    result 
    = callback.doInTransaction(conn);
                }
                
    catch (RuntimeException ex) {
                    doRollback(session, transaction);
                    
    throw ex;
                }
                
    catch (Error err) {
                    doRollback(session, transaction);
                    
    throw err;
                }
                
    //如果數(shù)據(jù)庫(kù)操作過(guò)程中沒(méi)有發(fā)生異常則提交事務(wù)
                transaction.commit();
            } 
    catch (WorkflowException e) {
                logger.error(
    "數(shù)據(jù)庫(kù)操作失敗,事務(wù)回滾也失敗!");
                
    throw e;
            } 
    catch (RuntimeException ex) {
                logger.error(
    "數(shù)據(jù)庫(kù)操作失敗,事務(wù)被回滾!");
                
    throw ex;
            } 
    catch (Error err) {
                logger.error(
    "數(shù)據(jù)庫(kù)操作失敗,事務(wù)被回滾!");
                
    throw err;
            } 
    finally {
                
    // 將session與當(dāng)前線程解除綁定
                TransactionSynchronizationManager.unbindResource(sessionFactory);
                doClose(session);
            }
            
    return result;
        }

        
    protected Session getSession(SessionFactory sessionFactory) {
            Session session 
    = SessionFactoryUtils.getSession(sessionFactory, true);
            FlushMode flushMode 
    = getFlushMode();
            
    if (flushMode != null) {
                session.setFlushMode(flushMode);
            }
            
    return session;
        }

        
    private void doRollback(Session session, Transaction transaction) {
            logger.debug(
    "數(shù)據(jù)庫(kù)操作異常,開(kāi)始回滾事務(wù)");
            
    try {
                transaction.rollback();
                logger.debug(
    "回滾事務(wù)成功!");
            }
            
    catch (Exception e) {
                logger.error(
    "回滾事務(wù)失敗!");
                
    throw new WorkflowException("回滾事務(wù)失敗!");
            } 
    finally {
                session.clear();
            }
        }

        
    private void doClose(Session session) {
            logger.debug(
    "開(kāi)始關(guān)閉連接");
            
    try {
                session.close();
            }
            
    catch (Exception e) {
                logger.error(
    "關(guān)閉連接失敗!");
                
    throw new WorkflowException("關(guān)閉連接失敗!");
            }
        }

        
    public FlushMode getFlushMode() {
            
    return flushMode;
        }

        
    public void setFlushMode(FlushMode flushMode) {
            
    this.flushMode = flushMode;
        }
    }

    public interface TransactionCallback {

        Object doInTransaction(Connection conn);
    }
    調(diào)用偽代碼:
        public void methodA(){
            TransactionTemplate transactionTemplate
    =new TransactionTemplate();
            transactionTemplate.execute(
    new TransactionCallback(){
                
    public Object doInTransaction(Connection conn) {
                    
    //客戶(hù)代碼
                    client.method1("1");
                    
    //我們代碼 直接使用
                    our.method2();
                    
    //客戶(hù)代碼
                    client.method3("l");
                    
    return null;  
                }
            });
        }




    http://m.tkk7.com/ronghao 榮浩原創(chuàng),轉(zhuǎn)載請(qǐng)注明出處:)
    posted on 2007-10-09 15:11 ronghao 閱讀(7741) 評(píng)論(5)  編輯  收藏 所屬分類(lèi): 工作日志

    FeedBack:
    # re: 結(jié)合spring+hibernate與jdbc的事務(wù)
    2007-10-09 18:40 | BeanSoft
    感謝分享!  回復(fù)  更多評(píng)論
      
    # re: 結(jié)合spring+hibernate與jdbc的事務(wù)
    2007-10-09 18:57 | 快樂(lè)的豬豬
    不錯(cuò)  回復(fù)  更多評(píng)論
      
    # re: 結(jié)合spring+hibernate與jdbc的事務(wù)
    2007-10-11 08:07 | ce
    不錯(cuò)。。。  回復(fù)  更多評(píng)論
      
    # re: 結(jié)合spring+hibernate與jdbc的事務(wù)[未登錄](méi)
    2007-10-12 07:49 | leo
    看的有點(diǎn)不懂。。。  回復(fù)  更多評(píng)論
      
    # re: 結(jié)合spring+hibernate與jdbc的事務(wù)
    2008-08-01 14:10 | asd
    不錯(cuò)。  回復(fù)  更多評(píng)論
      
    <2007年10月>
    30123456
    78910111213
    14151617181920
    21222324252627
    28293031123
    45678910

    關(guān)注工作流和企業(yè)業(yè)務(wù)流程改進(jìn)。現(xiàn)就職于ThoughtWorks。新浪微博:http://weibo.com/ronghao100

    常用鏈接

    留言簿(38)

    隨筆分類(lèi)

    隨筆檔案

    文章分類(lèi)

    文章檔案

    常去的網(wǎng)站

    搜索

    •  

    最新評(píng)論

    閱讀排行榜

    評(píng)論排行榜

    主站蜘蛛池模板: 国内精自视频品线六区免费| 中国一级特黄的片子免费 | 亚洲日本一区二区三区| 99久久婷婷免费国产综合精品| 国产亚洲欧洲Aⅴ综合一区| 国产99精品一区二区三区免费 | 无码日韩精品一区二区三区免费| 亚洲精品午夜国产VA久久成人| 中文字幕无线码免费人妻| 国产精品亚洲一区二区三区在线| 日韩免费高清播放器| 亚洲国语精品自产拍在线观看| 最近免费中文字幕大全高清大全1| 亚洲无线电影官网| 国产精品69白浆在线观看免费| 在线观看日本亚洲一区| 好爽好紧好大的免费视频国产| 无人视频在线观看免费播放影院 | 又粗又大又猛又爽免费视频 | 久久久久免费看黄A片APP| 亚洲AV成人一区二区三区在线看| 日韩免费无砖专区2020狼| 美女黄色免费网站| 亚洲AV无码专区国产乱码4SE| 最近最新高清免费中文字幕 | 亚洲一本之道高清乱码| 青草草在线视频永久免费| 成年大片免费高清在线看黄| 亚洲AV人人澡人人爽人人夜夜| 7723日本高清完整版免费| 美女视频黄视大全视频免费的| 亚洲色精品88色婷婷七月丁香| 97在线视频免费公开观看| 亚洲综合精品成人| 国产中文在线亚洲精品官网| 最近最好最新2019中文字幕免费| 亚洲AV成人精品日韩一区| 亚洲va在线va天堂va888www| 女人张开腿等男人桶免费视频| 9久热这里只有精品免费| youjizz亚洲|