<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
    問題背景:我們是一家工作流公司,客戶采購我們的產品后,將其嵌入其項目中。我們的工作流采用的是   spring+hibernate的方式,客戶項目則是jdbc直接進行數據庫操作。
    問題:客戶在其數據庫操作過程中需要調用我們的工作流接口,這樣就需要將我們的工作流操作與他們的業  務操作置于同一個事務中。我們的服務采用的都是spring的聲明式事務,而客戶采用的是對         connection進行事務處理。如何保證事務的一致性?
    想到的解決方案一:使用jta事務,用tomcat+jotm提供事務管理器。為什么一開始就想到要使用jta事務??實際上我們和客戶都是使用的同一個數據庫,為了方便,各自使用了不同的數據庫連接方式,使用jta的話確實有bt的意思在里面。但是事實上是我們的第一反應都是jta。最后沒有采用該方法的原因也很簡單:我沒有將jotm配置成功!汗一個。
    想到的解決方案二:將客戶的這些特定代碼用spring管理起來。因為要修改客戶部分代碼,這個方案遭到了客戶的強烈反對。于是放棄。
    想到的解決方案三:客戶數據庫操作與我們的服務使用同一個數據庫連接。然后編程處理事務。存在兩種方式:一種是把客戶的連接傳給我們,另一種則是把我們的連接傳給客戶。第一種方式對我們的影響太大,所以最后決定采用后一種方式:從hibernate session中獲取connection然后傳遞給客戶。接下來查看一下HibernateTemplate的execute()方法,思路就很簡單了:獲取定義的sessionFactory-->創建一個新的session并打開-->將session與當前線程綁定-->給客戶代碼返回connection-->打開事務-->客戶使用我們傳遞的connection進行數據庫操作-->我們不帶聲明事務的服務操作-->提交事務-->解除綁定。
    實際要注意的地方是:1、將session與當前線程綁定使用的TransactionSynchronizationManager.bindResource()方法,這樣在HibernateTemplate里才能找到session;
                        2、我們的服務一定要把聲明式事務徹底干掉,否則會有commit;
                        3、我們服務調用完畢后一定要flush session,否則客戶代碼不會感知數據庫里的數據變化。
    最終解決:使用了spring里常用的模板和回調。代碼如下:
    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");
            
    //創建一個新的session并打開
            logger.debug("Opening single Hibernate Session in TransactionTemplate");
            Session session 
    = getSession(sessionFactory);
            
    //將session與當前線程綁定
            TransactionSynchronizationManager.bindResource(sessionFactory, new SessionHolder(session));
            
    //獲取數據庫連接
            Connection conn = session.connection();
            Object result 
    = null;
            Transaction transaction 
    = null;
            
    try {
                
    //開始處理事務
                transaction = session.beginTransaction();
                
    try {
                    result 
    = callback.doInTransaction(conn);
                }
                
    catch (RuntimeException ex) {
                    doRollback(session, transaction);
                    
    throw ex;
                }
                
    catch (Error err) {
                    doRollback(session, transaction);
                    
    throw err;
                }
                
    //如果數據庫操作過程中沒有發生異常則提交事務
                transaction.commit();
            } 
    catch (WorkflowException e) {
                logger.error(
    "數據庫操作失敗,事務回滾也失敗!");
                
    throw e;
            } 
    catch (RuntimeException ex) {
                logger.error(
    "數據庫操作失敗,事務被回滾!");
                
    throw ex;
            } 
    catch (Error err) {
                logger.error(
    "數據庫操作失敗,事務被回滾!");
                
    throw err;
            } 
    finally {
                
    // 將session與當前線程解除綁定
                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(
    "數據庫操作異常,開始回滾事務");
            
    try {
                transaction.rollback();
                logger.debug(
    "回滾事務成功!");
            }
            
    catch (Exception e) {
                logger.error(
    "回滾事務失敗!");
                
    throw new WorkflowException("回滾事務失?。?/span>");
            } 
    finally {
                session.clear();
            }
        }

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

        
    public FlushMode getFlushMode() {
            
    return flushMode;
        }

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

    public interface TransactionCallback {

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




    http://m.tkk7.com/ronghao 榮浩原創,轉載請注明出處:)
    posted on 2007-10-09 15:11 ronghao 閱讀(7741) 評論(5)  編輯  收藏 所屬分類: 工作日志

    FeedBack:
    # re: 結合spring+hibernate與jdbc的事務
    2007-10-09 18:40 | BeanSoft
    感謝分享!  回復  更多評論
      
    # re: 結合spring+hibernate與jdbc的事務
    2007-10-09 18:57 | 快樂的豬豬
    不錯  回復  更多評論
      
    # re: 結合spring+hibernate與jdbc的事務
    2007-10-11 08:07 | ce
    不錯。。。  回復  更多評論
      
    # re: 結合spring+hibernate與jdbc的事務[未登錄]
    2007-10-12 07:49 | leo
    看的有點不懂。。。  回復  更多評論
      
    # re: 結合spring+hibernate與jdbc的事務
    2008-08-01 14:10 | asd
    不錯。  回復  更多評論
      
    <2007年10月>
    30123456
    78910111213
    14151617181920
    21222324252627
    28293031123
    45678910

    關注工作流和企業業務流程改進?,F就職于ThoughtWorks。新浪微博:http://weibo.com/ronghao100

    常用鏈接

    留言簿(38)

    隨筆分類

    隨筆檔案

    文章分類

    文章檔案

    常去的網站

    搜索

    •  

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 日本免费高清视频| AAAAA级少妇高潮大片免费看| 日韩人妻一区二区三区免费| 亚洲日韩精品无码专区网址| www成人免费观看网站| 国产啪亚洲国产精品无码| 一个人看的在线免费视频| 中文字幕亚洲激情| 最好免费观看高清在线| 久久国产亚洲观看| 91精品国产免费久久久久久青草| 亚洲成aⅴ人片在线观| 最近中文字幕无吗免费高清 | 777亚洲精品乱码久久久久久 | 国产午夜亚洲精品不卡电影| 免费一看一级毛片人| 午夜在线免费视频| 亚洲国产成人高清在线观看| 91大神在线免费观看| 亚洲成年网站在线观看| 四虎国产精品免费久久影院| 中国一级毛片免费看视频| 久久亚洲精品成人综合| 无码专区永久免费AV网站| 日韩精品无码免费视频| 亚洲国产成人片在线观看| 野花高清在线观看免费完整版中文| 亚洲国产精品无码久久| 国产亚洲人成网站在线观看| 免费无码成人AV在线播放不卡 | 深夜a级毛片免费无码| 国产AV无码专区亚洲A∨毛片| 手机看黄av免费网址| 精品视频免费在线| 亚洲欧洲在线观看| 国产精品国产自线拍免费软件| 国产精品免费大片一区二区| 亚洲成a人片在线观看中文!!!| 亚洲成人影院在线观看| 久视频精品免费观看99| 黄网站色成年片大免费高清|