<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://www.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)

    隨筆分類

    隨筆檔案

    文章分類

    文章檔案

    常去的網站

    搜索

    •  

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 一级日本高清视频免费观看| 免费观看黄色的网站| 亚洲国产综合91精品麻豆| 四虎成人精品一区二区免费网站| h片在线播放免费高清 | 亚洲免费观看网站| 日韩免费毛片视频| 久久青草免费91线频观看不卡| 亚洲中文字幕无码爆乳app| 亚洲va无码va在线va天堂| 免费羞羞视频网站| 日本免费一区二区三区四区五六区| 亚洲第一成年免费网站| 亚洲av无码无在线观看红杏| 日韩高清免费观看| 69视频在线是免费观看| 国产精品福利片免费看| 亚洲人成电影网站色www| 亚洲日本va午夜中文字幕一区| 亚洲 无码 在线 专区| 免费观看AV片在线播放| 中国一级全黄的免费观看| 亚洲高清国产拍精品熟女| 亚洲美女一区二区三区| 亚洲啪啪AV无码片| 免费一级毛片在线播放不收费| 18禁免费无码无遮挡不卡网站| 国产精品玖玖美女张开腿让男人桶爽免费看 | 免费一级e一片在线播放| 一个人看的www在线观看免费| 免费无码黄网站在线看| 猫咪免费观看人成网站在线| 亚洲 日韩 色 图网站| 4444亚洲国产成人精品| 亚洲AV福利天堂一区二区三| 久久精品亚洲男人的天堂| 国产一级一片免费播放| 四虎www成人影院免费观看| 午夜性色一区二区三区免费不卡视频 | 无人在线观看免费高清| a级毛片毛片免费观看久潮|