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

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

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

    posts - 189,comments - 115,trackbacks - 0

    畢業(yè)論文

    http://www.kj333.com/guest/hmhtml/hmlist31_1.htm

    以下是我搜集的一些論文網(wǎng)站

    你自己找一找吧!!
    ◆論文快車 http://www.lun-wen.com/ 提供論文資料收集、寫作指南、論文征稿,中國MBA、MPA、各類學(xué)術(shù)、畢業(yè)論文等資料。 484Gyi1
    ◆學(xué)生大論文中心 http://www.studa.com/newpaper/ 提供論文定做、發(fā)表等服務(wù),內(nèi)容涉及會計(jì)審計(jì)、財(cái)政稅收、計(jì)算機(jī)、經(jīng)濟(jì)學(xué)、管理學(xué)、法學(xué)、理學(xué)、工學(xué)、醫(yī)學(xué)、文學(xué)等20個(gè)學(xué)術(shù)類別。 376HnV7
    ◆蜂朝論文網(wǎng) http://www.51lunwen.com/subweb/thesis/main/index.asp提供畢業(yè)論文、本科論文、碩士論文等論文發(fā)表和定制等服務(wù)。 531hb9
    ◆教育教學(xué)論文網(wǎng) http://www.minaol.com/gb/art/ttd/index.asp以教育論文為主,含信息技術(shù)、計(jì)算機(jī)、德育、素質(zhì)教育、攝影、美術(shù)、化學(xué)、英語、語文、體育等方面論文。 815on7
    ◆中國園丁網(wǎng)論文大觀 http://www.teacher.net.cn/ 提供教育類論文。 203Fb2
    ◆法律論文資料庫 http://www.law-lib.com/lw/提供法學(xué)理論、憲法、行政法、刑法、民法、經(jīng)濟(jì)法、司法制度、國際法等分類論文。 78Jg8
    ◆論文網(wǎng) http://www.lunwen.net/提供論文寫作服務(wù)。 400Kxh8
    ◆吾愛論文網(wǎng)http://www.52paper.com/ 提供文理工管等十二大學(xué)科門類的期刊論文、畢業(yè)論文和職稱論文。 567wVAS6
    ◆幸福校園 http://www.happycampus.com.cn/ 論文、報(bào)告書、簡歷、考試情報(bào)等各種學(xué)術(shù)資料交流的中心。 36873o6
    ◆知新資訊http://www.paperscn.com/ 專業(yè)提供各種論文、課題資料,主要包括:教育論文、計(jì)算機(jī)論文、畢業(yè)論文、法律論文、學(xué)術(shù)論文、免費(fèi)論文、碩士論文、研究生論文、博士論文、經(jīng)濟(jì)論文、科技論文等。 203Ydu6
    ◆全程論文網(wǎng) http://www.lunwen51.net/一個(gè)專業(yè)代理職稱論文、畢業(yè)論文、學(xué)術(shù)論文寫作指導(dǎo)、論文推薦公開刊物發(fā)表(核心、優(yōu)秀期刊)的網(wǎng)站。 642pjiY2
    ◆論文商務(wù)中心http://doc.cei.gov.cn/ 是一個(gè)開放式的、保護(hù)版權(quán)的、網(wǎng)上論文精品自選超市。 127JoVq5
    論文發(fā)表咨詢網(wǎng) http://www.csepg.com/ 202wdx01
    語言學(xué)論文http://chinese.pku.edu.cn/yuyinyj/shenjiong.htm 2252du8

    ◆論文資料網(wǎng) http://www.51paper.net/ 提供論文資料服務(wù)的專業(yè)網(wǎng)站,含MBA論文資料、中小企業(yè)論文、物流供應(yīng)鏈論文、財(cái)經(jīng)論文、電子商務(wù)論文、論文參考資料。 1550x9
    ◆論文帝國 http://www.51paper.net/ 含論文查詢、發(fā)布論文及***外交、社會行政、勞動(dòng)人事、新聞傳播、法律、財(cái)經(jīng)等論文。 828Ol9
    ◆畢業(yè)論文網(wǎng)http://www.bylw.net/ 實(shí)施全免費(fèi)畢業(yè)論文資料服務(wù),不涉及向網(wǎng)友收費(fèi)內(nèi)容。 380JTi1
    ◆論文資料站 http://lwzl.com/免費(fèi)為廣大學(xué)子提供論文資料查詢、交流的優(yōu)良平臺。 662Y23z5
    ◆世界論文網(wǎng) http://www.worldthesis.com/ 收集并接受委托,發(fā)布國際優(yōu)秀作品(論文)。 92N64
    ◆中國論文網(wǎng) http://www.lw99.com/ 提供大量專業(yè)論文、大學(xué)畢業(yè)論文,有各種層次的內(nèi)容,特別適合各大專院校畢業(yè)生、社會各界論文愛好者和各機(jī)關(guān)人員作參考學(xué)習(xí)之用,免去您各方查找資料的麻煩。 719va7
    ◆天下網(wǎng) http://txlw.com/ 論文老牌名站,由在讀博士、碩士生創(chuàng)辦。網(wǎng)站側(cè)重于為論文寫作者(尤其是對撰寫畢業(yè)論文的朋友)提供寫作指導(dǎo)。 2285Vg1
    ◆國際優(yōu)秀論文http://txlw.com/ 分為科技論文、醫(yī)學(xué)論文、教育論文三大版塊。 43QOES3

    臺灣博碩士論文資訊網(wǎng) http://datas.ncl.edu.tw/theabs/1/ 231pEO1
    論文網(wǎng) http://lwdb.vip.sina.com/ 254VPJ2
    大學(xué)生論文庫 http://www.syiae.com/lunwen/ 752if5
    華夏論文網(wǎng) http://hxlw.vip.sina.com/ 656191
    論文薈萃http://www.oh100.com/teach/teacher/lunwen/ 261kpjs5
    論文秘書網(wǎng)http://www.wenshu.net/ 869YD87
    論文指導(dǎo)網(wǎng) http://lunwen.zzcollege.net/ 739gG3
    中國大學(xué)生論文網(wǎng)http://www.wenshu.net/ 697KC4
    大學(xué)生論文資訊網(wǎng) http://www.thesis4u.com/ 424ZzIL6
    輕松論文網(wǎng) http://www.paperease.com/ 72QHgm8
    全國優(yōu)秀博士學(xué)位論文評選 http://www.cdgdc.edu.cn/yxbslw/yxbslw.htm 4667wI1
    體育教學(xué)論文http://pe.stedu.net/mywz/tyjx.htm 9891UX94
    體育論文 http://www.zxty.net/product4.htm 303RMCE1
    新科論文網(wǎng)http://www.xklw.com/# 4944f07
    信息化教育論文 http://www.yxedu.net/it/lunwen.htm 283RBp1
    農(nóng)業(yè)論文 http://www.agrionline.net.cn/keji/lunwenzy/ 688mOMA8
    中國總經(jīng)理網(wǎng)論文集http://www.cnceo.com/school/lwj.asp 748YbJ6
    工程論文服務(wù)網(wǎng)http://infobuild.vip.sina.com/ 948kBt63
    金融論文在線 http://www.finance-cn.com/ 6635Zl7
    才思論文網(wǎng) http://thesis.xiloo.com/ 423l5PH8
    論文資源網(wǎng) http://lunw.vip.sina.com/ 44uI9G3
    經(jīng)濟(jì)論文 http://www.gjmy.com/jjlw.asp 723HES23
    論文選萃http://www.chinampaonline.com/lunwen/ 543C76
    活動(dòng)教育研究論文http://www.21cae.net/activeteach/activearticle.htm 901heD1
    畢業(yè)生論文庫 http://lib.blcu.edu.cn/dt1000/bys/bys.htm 3644l4
    能源論文 http://www.china5e.com/dissertation/default.htm 297PG1
    會計(jì)文苑-優(yōu)秀論文 http://www.chinaacc.com/wenyuan/lunwen/ 901MS7
    中國廣電技術(shù)論文 http://www.chinabctv.com/bctvlw/index.asp 820OJ07
    教育教學(xué)論文交流網(wǎng) http://www.minaol.com/gb/art/ttd/index.asp 178sxqw4
    食品論文http://china-foods.net.cn/discourse.asp 170YcYB8
    管理在線論文 http://www.hao3721.com/main.asp 22kaP8
    中國科技論文在線 http://www.paper.edu.cn/home.jsp 960zUkA6
    MBA論文全集 http://mba.001.com.cn/mbamba.htm 244u61
    物理論文集 http://www.physicswd.com/ 620zwW1
    中國交通技術(shù)論壇資料庫 http://www.tranbbs.com/article/ 620zwW1
    中國路橋工程論文資料中心 http://www.lqzx.com/lunwen.htm 748tOd4
    中國論文發(fā)表網(wǎng)http://www.fabiao.cn/ 884SQDc7
    翰林論文網(wǎng)http://www.hlpaper.com900QBIk6
    ?

    posted @ 2006-03-22 11:19 MEYE 閱讀(458) | 評論 (0)編輯 收藏

    一個(gè)很不錯(cuò)的數(shù)據(jù)庫連接池實(shí)現(xiàn),備份之

    import java.sql.*;
    import java.io.*;
    import java.util.*;
    public class DBConnectionManager {

      private static int clients = 0;
      private static DBConnectionManager instance;
      private Vector drivers = new Vector();
      private PrintWriter log;
      private Hashtable pools = new Hashtable();


      public DBConnectionManager() {
        init();
      }
      private void log(String msg) {
        log.println(new java.util.Date() + ": " + msg);
      }

      /**
      * 將文本信息與異常寫入日志文件
      */
      private void log(Throwable e, String msg) {
        log.println(new java.util.Date() + ": " + msg);
        e.printStackTrace(log);
      }

      public static synchronized  DBConnectionManager getInstance() {
        if (instance == null) {
          instance = new DBConnectionManager();
        }
        clients++;
        return instance;
      }
      private void init() {
        InputStream is = getClass().getResourceAsStream("/db.properties");
        Properties dbProps = new Properties();
        try {
          dbProps.load(is);
        }
        catch (Exception e) {
            System.err.println("Can not read the properties file. " +
            "Make sure db.properties is in the CLASSPATH");
            return;
        }
        loadDrivers(dbProps);
        createPools(dbProps);
      }
      public void freeConnection(String name, Connection con) {
        DBConnectionPool pool = (DBConnectionPool) pools.get(name);
        if (pool != null) {
          pool.freeConnection(con);
        }
      }
      public Connection getConnection(String name) {
        DBConnectionPool pool = (DBConnectionPool) pools.get(name);
        if (pool != null) {
          return pool.getConnection();
        }
        return null;
      }
      public Connection getConnection(String name, long time) {
        DBConnectionPool pool = (DBConnectionPool) pools.get(name);
        if (pool != null) {
          return pool.getConnection(time);
        }
        return null;
      }
      public synchronized void release() {
        // 等待直到最后一個(gè)客戶程序調(diào)用
        if (--clients != 0)
        {
          return;
        }
        Enumeration allPools = pools.elements();
        while (allPools.hasMoreElements())
        {
          DBConnectionPool pool = (DBConnectionPool)allPools.nextElement();
          pool.release();
        }
        Enumeration allDrivers = drivers.elements();
        while (allDrivers.hasMoreElements())
        {
          Driver driver = (Driver) allDrivers.nextElement();
          try {
            DriverManager.deregisterDriver(driver);
            log("撤銷JDBC驅(qū)動(dòng)程序 " + driver.getClass().getName()+"的注冊");
          }
          catch (SQLException e) {
          log(e, "無法撤銷下列JDBC驅(qū)動(dòng)程序的注冊: " + driver.getClass().getName());
          }
        }
      }


    /*
    drivers=sun.jdbc.odbc.JdbcOdbcDriver jdbc.idbDriver

    logfile=D:\\user\\src\\java\\DBConnectionManager\\log.txt

    idb.url=jdbc:idb:c:\\local\\javawebserver1.1\\db\\db.prp

    idb.maxconn=2

    access.url=jdbc:odbc:demo

    access.user=demo

    access.password=demopw

    */
      private void loadDrivers(Properties props) {
        String driverClasses = props.getProperty("drivers");
        StringTokenizer st = new StringTokenizer(driverClasses);
        while (st.hasMoreElements()) {
          String driverClassName = st.nextToken().trim();
          try {
            Driver driver = (Driver)
              Class.forName(driverClassName).newInstance();
            DriverManager.registerDriver(driver);
            drivers.addElement(driver);
         //   Log.log("Registered JDBC driver " + driverClassName);
          }
          catch (Exception e) {
          //  Log.log("Can not register JDBC driver: " + driverClassName + ", Exception: " + e.toString()));
          }
        }
      }
      private void createPools(Properties props) {
        Enumeration propNames = props.propertyNames();
        while (propNames.hasMoreElements())
        {
          String name = (String) propNames.nextElement();
          if (name.endsWith(".url"))
          {
            String poolName = name.substring(0, name.lastIndexOf("."));
            String url = props.getProperty(poolName + ".url");
            if (url == null) {
           //   Log.log("No URL specified for " + poolName);
              continue;
            }
            String user = props.getProperty(poolName + ".user");
            String password = props.getProperty(poolName + ".password");
            String maxconn = props.getProperty(poolName + ".maxconn", "0");
            int max;
            try {
              max = Integer.valueOf(maxconn).intValue();
            }
            catch (NumberFormatException e) {
          //    Log.log("Invalid maxconn value " + maxconn + " for " +   poolName);
              max = 0;
            }
            DBConnectionPool pool =
              new DBConnectionPool(poolName, url, user, password, max);
            pools.put(poolName, pool);
          //  Log.log("Initialized pool " + poolName);
          }
        }
      }

      class DBConnectionPool {
        private int checkedOut;
        private Vector freeConnections = new Vector();
        private int maxConn;
        private String name;
        private String password;
        private String URL;
        private String user;

        /**
        * 創(chuàng)建新的連接池
        *
        * @param name 連接池名字
        * @param URL 數(shù)據(jù)庫的JDBC URL
        * @param user 數(shù)據(jù)庫帳號,或 null
        * @param password 密碼,或 null
        * @param maxConn 此連接池允許建立的最大連接數(shù)
        */
        public DBConnectionPool(String name, String URL, String user
            , String password,   int maxConn)
        {
          this.name = name;
          this.URL = URL;
          this.user = user;
          this.password = password;
          this.maxConn = maxConn;
        }

      /**
      * 將不再使用的連接返回給連接池
      *
      * @param con 客戶程序釋放的連接
      */
        public synchronized void freeConnection(Connection con) {
        // 將指定連接加入到向量末尾
          freeConnections.addElement(con);
          checkedOut--;
          notifyAll();
        }

        /**
         * 從連接池獲得一個(gè)可用連接.如沒有空閑的連接且當(dāng)前連接數(shù)小于最大連接
         * 數(shù)限制,則創(chuàng)建新連接.如原來登記為可用的連接不再有效,則從向量刪除之,
         * 然后遞歸調(diào)用自己以嘗試新的可用連接.
         */
        public synchronized Connection getConnection()
        {
          Connection con = null;
          if (freeConnections.size() > 0)
          {
          // 獲取向量中第一個(gè)可用連接
            con = (Connection) freeConnections.firstElement();
            freeConnections.removeElementAt(0);
            try {
              if (con.isClosed())
              {
                log("從連接池" + name+"刪除一個(gè)無效連接");
                // 遞歸調(diào)用自己,嘗試再次獲取可用連接
                con = getConnection();
              }
            }
            catch (SQLException e)
            {
              log("從連接池" + name+"刪除一個(gè)無效連接");
              // 遞歸調(diào)用自己,嘗試再次獲取可用連接
              con = getConnection();
            }
          }
          else if (maxConn == 0 || checkedOut < maxConn)
          {
            con = newConnection();
          }
          if (con != null) {
            checkedOut++;
          }
          return con;
        }

      /**
      * 從連接池獲取可用連接.可以指定客戶程序能夠等待的最長時(shí)間
      * 參見前一個(gè)getConnection()方法.
      *
      * @param timeout 以毫秒計(jì)的等待時(shí)間限制
      */
        public synchronized Connection getConnection(long timeout)
        {
          long startTime = new java.util.Date().getTime();
          Connection con;
          while ((con = getConnection()) == null)
          {
            try {
              wait(timeout);
            }
            catch (InterruptedException e) {}
            if ((new java.util.Date().getTime() - startTime) >= timeout)
            {
            // wait()返回的原因是超時(shí)
              return null;
            }
          }
          return con;
        }

      /**
      * 關(guān)閉所有連接
      */
        public synchronized void release()
        {
          Enumeration allConnections = freeConnections.elements();
          while (allConnections.hasMoreElements())
          {
            Connection con = (Connection) allConnections.nextElement();
            try {
            con.close();
              log("關(guān)閉連接池" + name+"中的一個(gè)連接");
            }
            catch (SQLException e) {
              log(e, "無法關(guān)閉連接池" + name+"中的連接");
            }
          }
          freeConnections.removeAllElements();
        }

      /**
      * 創(chuàng)建新的連接
      */
        private Connection newConnection()
        {
          Connection con = null;
          try {
            if (user == null) {
              con = DriverManager.getConnection(URL);
            }
            else {
              con = DriverManager.getConnection(URL, user, password);
            }
            log("連接池" + name+"創(chuàng)建一個(gè)新的連接");
          }
          catch (SQLException e) {
            log(e, "無法創(chuàng)建下列URL的連接: " + URL);
            return null;
          }
          return con;
        }
      }
    }

    posted @ 2006-03-16 10:42 MEYE 閱讀(367) | 評論 (0)編輯 收藏
    J2EE設(shè)計(jì)(J2EE in Action)
     

    學(xué)會選擇何種設(shè)計(jì)模式和構(gòu)架才可以開發(fā)出最好的企業(yè)程序

    摘要

    文章中,列舉了Chris Richardson在POJOs in Action(2006年1月份出版)的例子,該例子舉了5個(gè)程序設(shè)計(jì)者在設(shè)計(jì)企業(yè)應(yīng)用程序中都會問自己的問題.

    如果我們盲目的使用POJOs技術(shù)(plain-old Java objects)和輕量級構(gòu)架,那么我們在通過EJB建立分布式企業(yè)級JAVA程序時(shí)就可能會出現(xiàn)錯(cuò)誤。每種技術(shù)都有它的強(qiáng)項(xiàng)和弱項(xiàng),而根據(jù)實(shí)際情況選擇最合適的技術(shù)是最重要的。
    這篇文章主要討論企業(yè)應(yīng)用程序的設(shè)計(jì)模式和輕量級構(gòu)架。為了讓你在程序中高效的使用這些設(shè)計(jì)模式和輕量級構(gòu)架,這里提供了一個(gè)決策構(gòu)架. 這個(gè)構(gòu)架包含了5個(gè)在設(shè)計(jì)程序或者是單獨(dú)用例的業(yè)務(wù)邏輯(business logic for an individual use-case)的過程中必須回答的問題(decision-making framework)。這里特意加上了設(shè)計(jì)方案和對這種決策的理解,這樣可以很大的提高你的軟件質(zhì)量。

    在這篇文章中,你會看到對5種決策的簡述,并且我會簡單扼要的介紹每種設(shè)計(jì)決策的選項(xiàng)(options)和他們的優(yōu)缺點(diǎn)。

    版權(quán)聲明:任何獲得Matrix授權(quán)的網(wǎng)站,轉(zhuǎn)載時(shí)請務(wù)必保留以下作者信息和鏈接
    作者:Chris Richardson;tain198127(作者的blog:http://blog.matrix.org.cn/page/tain198127)
    原文:http://www.javaworld.com/javaworld/jw-01-2006/jw-0130-pojo.html
    譯文:http://www.matrix.org.cn/resource/article/44/44254_J2EE+design+decisions.html
    關(guān)鍵字:J2EE;design;decisions

    業(yè)務(wù)邏輯和數(shù)據(jù)庫訪問決策

    這里有2種完全不同的方法來設(shè)計(jì)JAVA企業(yè)程序,其中一種選擇是采用標(biāo)準(zhǔn)EJB2實(shí)現(xiàn)途徑(approach)。我更愿意稱這種方法為重量級實(shí)現(xiàn)途徑,當(dāng)你使用重量級實(shí)現(xiàn)途徑時(shí)你需要用會話beans(session bean)和消息驅(qū)動(dòng) beans(message-driven bean)去實(shí)現(xiàn)業(yè)務(wù)邏輯。你也可以使用DAOs(data access object)或者實(shí)體bean去訪問業(yè)務(wù)邏輯

    另外一種選擇是使用POJOs 和輕量級構(gòu)架,這種方式我稱為POJO實(shí)現(xiàn)途徑。當(dāng)使用POJOs實(shí)現(xiàn)途徑時(shí),你的業(yè)務(wù)邏輯完全由POJO來實(shí)現(xiàn)。你可以使用持久型構(gòu)架又叫做對象/關(guān)系映射構(gòu)架(a.k.a=also know as )例如Hibernate 或者 JDO來訪問數(shù)據(jù)庫,再用Spring AOP(面向?qū)用婢幊蹋﹣硖峁┢髽I(yè)服務(wù),比如事務(wù)管理和安全。
    EJB3由于融合了POJOs和其他一些輕量級概念,所以對兩者(指輕量級和重考鍛揪叮┑那?植皇嗆芮宄?>俑隼?櫻?OJO中的實(shí)體bean既可以再EJB容器內(nèi)運(yùn)行,也可以再EJB容器外運(yùn)行,然而POJOs中的會話bean和消息驅(qū)動(dòng)bean仍然有重量級的行為,因?yàn)樗麄冎荒茉贓JB容器內(nèi)部運(yùn)行。所以,顯而易見的,EJB3既是重量級的又有POJO的特性。EJB3中的實(shí)體bean是輕量級實(shí)現(xiàn)途徑中的一部分。

    在開發(fā)過程中,首要的是從各種各樣的設(shè)計(jì)中選擇到底采用重量級實(shí)現(xiàn)途徑還是采用POJO實(shí)現(xiàn)途徑。決策可以影響程序的幾個(gè)方面,包括業(yè)務(wù)邏輯結(jié)構(gòu)和數(shù)據(jù)訪問機(jī)制。為了幫助從兩種實(shí)現(xiàn)途徑中擇其一,來看這張典型的企業(yè)應(yīng)用程序結(jié)構(gòu)圖,結(jié)構(gòu)圖在圖示1中,而且在設(shè)計(jì)過程中就必須判斷到底使用那種策略。


    Figure 1. A typical application architecture and the key business logic and database access design decisions. 

    程序由網(wǎng)絡(luò)基本表示層、業(yè)務(wù)層、持久層組成。網(wǎng)絡(luò)基本表示層負(fù)責(zé)HTTP請求和為一般的瀏覽器客戶端、XML和其他的胖體客戶端生成HTML,比如為Ajax基本客戶端生成HTML。業(yè)務(wù)層被表示層調(diào)用,用來實(shí)現(xiàn)程序業(yè)務(wù)邏輯。持久層被業(yè)務(wù)邏輯層用來訪問外部數(shù)據(jù)源,比如數(shù)據(jù)庫和其他程序。

    表示層的設(shè)計(jì)不在本篇文章討論之內(nèi),來看圖表的其他部分,我們需要決定業(yè)務(wù)層結(jié)構(gòu)的接口,這個(gè)接口是提供給表示層以及其他客戶端的。而且還需要決定怎樣訪問能供多個(gè)程序訪問的數(shù)據(jù)庫。我們還必須決定如何處理短期事務(wù)處理事務(wù)和長期事務(wù)處理事務(wù)的并發(fā)問題。這些加起來一共有5種決策。每種決策都是要設(shè)計(jì)者來制定,為了能看懂演示圖(big picture)要求每個(gè)開發(fā)者也都了解這些策略。

    這些決策直接決定程序業(yè)務(wù)和表示層設(shè)計(jì)的特點(diǎn)。當(dāng)然,還要決定一些其他很重要的決策。比如業(yè)務(wù)處理(transactions)、安全問題、緩存問題以及如何整合程序,但是關(guān)于這些問題通常在其他文獻(xiàn)中討論
    在圖表1中顯示的五種決策,每種決策都有多種選擇。每種選擇根據(jù)它要解決的實(shí)際問題都有相應(yīng)的優(yōu)缺點(diǎn)。后續(xù)章節(jié)中,你會發(fā)現(xiàn)每種決策針對一個(gè)或多個(gè)領(lǐng)域時(shí),在功能性、易開發(fā)性、可維護(hù)性和可用性方面有不同的平衡點(diǎn)。盡管我是POJO實(shí)現(xiàn)途徑的超級大FANS,但是仍然需要了解其優(yōu)缺點(diǎn),以便于為你的程序做最好的選擇
    下面我們來了解一下每種決策的大綱和其選項(xiàng)。

    決策1:組織業(yè)務(wù)邏輯

    現(xiàn)在,很多的注意力都集中在某項(xiàng)技術(shù)的優(yōu)點(diǎn)和缺點(diǎn),盡管這很重要,但是在本質(zhì)上你需要了解如何建構(gòu)你的業(yè)務(wù)邏輯。如果不考慮如何組織就去寫代碼是非常簡單的。例如,為一個(gè)會話BEAN添加代碼要比在域模式(domain model.: An object model of the domain that incorporates both behavior and data.)中判斷應(yīng)該添加那種新特性要簡單的多。理論上你仍然需要刻意的為你的軟件設(shè)計(jì)最合適的業(yè)務(wù)邏輯。畢竟我相信你有過修改別人垃圾結(jié)構(gòu)代碼的慘痛經(jīng)驗(yàn)

    關(guān)鍵的決策是:到底應(yīng)該用面向?qū)ο蟮膶?shí)現(xiàn)途徑還是面向過程的實(shí)現(xiàn)途徑來實(shí)現(xiàn)你的程序。這個(gè)不是關(guān)于技術(shù)的決策,但是你技術(shù)上的決策可以潛在的約束你的業(yè)務(wù)邏輯的組織結(jié)構(gòu)。采用EJB2技術(shù),有利于面向過程設(shè)計(jì),然而POJOs和輕量級構(gòu)架可以讓你為特殊的程序選擇最好的實(shí)現(xiàn)途徑

    采用過程式設(shè)計(jì)
    雖然我是一個(gè)面向?qū)ο髮?shí)現(xiàn)途徑(指前文的使用POJO和LIGHTFRAMEWORK)的倡導(dǎo)者,但是有些情況下面向?qū)ο髮?shí)現(xiàn)途徑有些大材小用,比如你只想實(shí)現(xiàn)一個(gè)非常簡單的業(yè)務(wù)邏輯。而且,有時(shí)候,面向?qū)ο髮?shí)現(xiàn)途徑不太可行-?比如,你沒有持久層構(gòu)架來將你的對象映射到數(shù)據(jù)庫中,在這種情況下,更好的方法是編寫面向過程的代碼,而且采用Martin Fowler稱作事務(wù)腳本(Transaction Script)的設(shè)計(jì)模式,要比采用面向?qū)ο髮?shí)現(xiàn)途徑設(shè)計(jì)要好,因?yàn)槟阒恍枰獙懸粋€(gè)方法來調(diào)用事務(wù)處理腳本去處理表示層的請求。

    采種這種實(shí)現(xiàn)途徑的一個(gè)很重要的特點(diǎn)是,用于實(shí)現(xiàn)某種行為的類和數(shù)據(jù)存儲區(qū)是分開的。在EJB2的應(yīng)用程序中,這種方式的業(yè)務(wù)邏輯和圖表2中的設(shè)計(jì)是非常相似的。這種設(shè)計(jì)的核心全都集中在EJB或者POJO的行為上,因?yàn)樗麄儗?shí)現(xiàn)了事務(wù)腳本,并且還操作那些 “啞”對象數(shù)據(jù)(因?yàn)樗麄冎粨碛泻苌俚男袨椋蟛糠侄际菙?shù)據(jù))。因?yàn)榇蟛糠值男袨槎技性谏倭康拇笮皖惿希源a會變的很難理解與維護(hù)。


    Figure 2. The structure of a procedural design: large transaction script classes and many small data objects

    這種設(shè)計(jì)具有高面向過程的特性,而且基本不依靠面向?qū)ο笳Z言的特性。如果你曾經(jīng)使用過C或者其他非面向?qū)ο笳Z言的話,你應(yīng)該用過這種設(shè)計(jì)模式。如果這種模式很適合你的設(shè)計(jì)的話,用這種模式設(shè)計(jì)也是一種不錯(cuò)的選擇。

    這種直觀的過程式開發(fā)途徑,非常的誘人,因?yàn)槟阒恍枰獙懘a就好了,不用考慮如何組織你的類文件。但問題是,如果你的業(yè)務(wù)邏輯非常的復(fù)雜,那么你的代碼會變的噩夢般的難以維護(hù)。所以,除非你要寫的程序非常的簡單,否則你應(yīng)該用面向?qū)ο笤O(shè)計(jì)你的程序,而不要受面向過程的代碼的誘惑。

    采用面向?qū)ο笤O(shè)計(jì)
    在面向?qū)ο笤O(shè)計(jì)中,業(yè)務(wù)邏輯是由對象模型構(gòu)成的,對象模型是由許多小類組成的關(guān)系網(wǎng)。這些類直接體現(xiàn)的是問題域的解決方法,如圖3所示,在這種模式中,有些類只有數(shù)據(jù),有些類只有行為,但是大多數(shù)的則兩者都有,這是優(yōu)秀的類設(shè)計(jì)的一種特點(diǎn)。


    Figure 3. The structure of a domain model: small classes that have state and behavior

    面向?qū)ο笤O(shè)計(jì)有許多的好處,包括可以提高可維護(hù)性和可延展性。你可以用EJB2的實(shí)體bean來實(shí)現(xiàn)一個(gè)簡單的對象模型。但是如果像要獲得更多的好處的話,必須要使用POJOs技術(shù)和輕量級持久層構(gòu)架??比如Hibernate和JDO技術(shù)。POJO可以讓你開發(fā)豐富的模型,這些模型可以擁有繼承和回調(diào)等特點(diǎn)。而輕量級持久層構(gòu)架可以讓你很簡單的從對象模型映射到數(shù)據(jù)庫。

    對象模型的另外一個(gè)名字是域模型,F(xiàn)owler稱這種由面向?qū)ο笸緩絹黹_發(fā)的業(yè)務(wù)邏輯叫做域模型設(shè)計(jì)模式。(就是類的設(shè)計(jì)是直接用來解決問題的,則這種設(shè)計(jì)模式叫做域模型設(shè)計(jì)模式)

    表模型設(shè)計(jì)模式
    我曾經(jīng)一直用域模型和事務(wù)處理腳本模型設(shè)計(jì)應(yīng)用程序。但是有一次我聽說JAVA企業(yè)應(yīng)用程序可以用第三種途徑來實(shí)現(xiàn),這種途徑就是Fowler所說的表模型設(shè)計(jì)模式。這種模式比事務(wù)處理腳本模式更加的結(jié)構(gòu)化,因?yàn)樗鼮閿?shù)據(jù)庫中的每個(gè)表都寫了一個(gè)類,而這個(gè)類中實(shí)現(xiàn)了所有對這個(gè)表的操作代碼,這個(gè)類就是表模型類。(我的解釋就是為每個(gè)表專門寫個(gè)類,對表的所有操作,全都由這個(gè)類中的方法實(shí)現(xiàn),相當(dāng)于用一個(gè)類模擬的數(shù)據(jù)庫中的表)。和事務(wù)處理腳本模式相比,它將數(shù)據(jù)和行為分別封裝到了不同的類中,因?yàn)楸砟P皖惖膶?shí)例相當(dāng)于真實(shí)數(shù)據(jù)庫中的數(shù)據(jù),這當(dāng)然要比單獨(dú)的一條記錄要好的多。最后,可維護(hù)性成了問題,然而表模型設(shè)計(jì)模式還是有一些好處的。


    決策2:封裝業(yè)務(wù)邏輯

    前面幾章,我沒有提及如何組織業(yè)務(wù)邏輯。你必須決定業(yè)務(wù)邏輯有什么樣的接口。業(yè)務(wù)邏輯的接口由一些數(shù)據(jù)和方法組成,這些數(shù)據(jù)和方法由表示層來調(diào)用。在設(shè)計(jì)接口時(shí)重點(diǎn)需要考慮的是:應(yīng)該封裝哪些業(yè)務(wù)邏輯的操作,而哪些操作不應(yīng)該顯示給表示層。封裝接口可以提高程序的可維護(hù)性,因?yàn)橥ㄟ^隱藏業(yè)務(wù)邏輯的操作細(xì)節(jié),可以實(shí)現(xiàn)修改業(yè)務(wù)邏輯而不影響表示層。缺點(diǎn)是,你必須為封裝業(yè)務(wù)邏輯而特意的寫很多的代碼。

    你還需要考慮其他重要的問題,比如如何處理事務(wù)處理,安全,和遠(yuǎn)程調(diào)用問題。通常這些也是業(yè)務(wù)邏輯接口要負(fù)責(zé)的問題。為了保證數(shù)據(jù)的連貫性,業(yè)務(wù)層的接口必須保證每個(gè)事務(wù)處理中的調(diào)用都能執(zhí)行。同樣,也要驗(yàn)證調(diào)用者是否有權(quán)限調(diào)用業(yè)務(wù)方法。業(yè)務(wù)層接口還要負(fù)責(zé)處理一些遠(yuǎn)程客戶端的問題。

    來考慮一下選項(xiàng)。

    EJB session fa?ade
    經(jīng)典的J2EE解決方案是:用EJB來封裝業(yè)務(wù)邏輯-基本的session facade。EJB容器提供事務(wù)處理管理,安全,分布式事務(wù)處理和遠(yuǎn)程訪問。Facade方式可以通過封裝業(yè)務(wù)邏輯來提高程序可維護(hù)性。粗糙型(Coarse-grained) API通過減少表示層對業(yè)務(wù)層的訪問次數(shù),而提高性能(因?yàn)樗鼘Ω鱾€(gè)業(yè)務(wù)流程的處理再封裝了一次,所以對底層的業(yè)務(wù)流程來說,它的API是比較粗糙的,這里也許翻譯的不好。請大家見諒)。因?yàn)闇p少調(diào)用的次數(shù),可以減少對數(shù)據(jù)庫事務(wù)處理的次數(shù),還可以提高對象在緩沖區(qū)的機(jī)會。如果表示層通過遠(yuǎn)程訪問業(yè)務(wù)層,則這種API還可以減少網(wǎng)絡(luò)負(fù)擔(dān)。圖表4給出了一個(gè)EJB-based session facade的例子。


    Figure 4. Encapsulating the business logic with an EJB session fa?ade

    在這種設(shè)計(jì)模式中,表示層也許是通過遠(yuǎn)程來調(diào)用facade(相當(dāng)于session的一個(gè)高級接口),EJB容器從facade中得到這個(gè)調(diào)用,并驗(yàn)證調(diào)用者的權(quán)限,然后開始一個(gè)業(yè)務(wù)處理。這個(gè)時(shí)候facade調(diào)用底層的業(yè)務(wù)對象,而這些業(yè)務(wù)對象負(fù)責(zé)實(shí)現(xiàn)具體的業(yè)務(wù)邏輯。等Facade返回后,EJB容器提交業(yè)務(wù)處理或者讓該業(yè)務(wù)處理循環(huán)等待。

    不幸的是,使用EJB session facade有一些嚴(yán)重的缺點(diǎn)。比如,EJB的會話bean只能在EJB容器中運(yùn)行,這樣就托慢了開發(fā)和測試周期。另外,如果用EJB2,則用來向表示層傳輸數(shù)據(jù)的數(shù)據(jù)傳輸對象的開發(fā)和維護(hù)就會變的很枯燥而且曠日持久。

    POJO facade
    對于許多程序來說,更好的實(shí)現(xiàn)途徑是用POJO facade和AOP協(xié)作。比如負(fù)責(zé)管理事務(wù)處理、表示層的連接和安全問題的Spring 構(gòu)架。POJO facade對業(yè)務(wù)層的封裝風(fēng)格和EJB facade很相似,通常也可以用一樣的公共方法。而POJO和EJB關(guān)鍵區(qū)別是用POJO代替了EJB,用AOP提供的服務(wù)(例如業(yè)務(wù)處理管理和安全機(jī)制)替代了EJB容器。表5中,顯示了用POJO facade的例子。


    Figure 5. Encapsulating the business logic with a POJO fa?ade

    表示層調(diào)用POJO facade, POJO facade 調(diào)用業(yè)務(wù)對象。和EJB容器截獲EJB facade方式一樣,AOP通過“攔截機(jī)”來截獲POJO facade,并驗(yàn)證調(diào)用者的權(quán)限,然后開始提交業(yè)務(wù)處理或讓該業(yè)務(wù)循環(huán)等待。

    通過在應(yīng)用程序服務(wù)器外部開發(fā)和調(diào)試業(yè)務(wù)邏輯,對POJO facade的開發(fā)可以變的很簡單,同時(shí)還可以獲得許多EJB中會話Bean的好處,比如聲明事務(wù)處理和安全。關(guān)鍵是,你可以少寫點(diǎn)代碼。你可以避免寫數(shù)據(jù)傳輸對象類,因?yàn)镻OJO facade可以將對象域直接反饋給表示層;你可以使用依賴注射的方式來將應(yīng)用程序組裝起來,而不用在為JNDI寫查找代碼了。

    然而,有些時(shí)候不能那用POJO facade,比如它不能參與到遠(yuǎn)程客戶端建立的分布式事務(wù)處理。

    暴露模型域模式
    使用facade的一個(gè)缺點(diǎn)是你必須寫額外的代碼,而且負(fù)責(zé)將對象域返回給表示層的代碼很容易出錯(cuò)。如果表示層設(shè)法調(diào)用某個(gè)對象,而業(yè)務(wù)層卻沒有提供該對象,也會增加runtime error出現(xiàn)的機(jī)會。如果你用JDO , Hibernate或者EJB3,則可以避免這種問題,方法是:將模型域(session區(qū)域)暴露給表示層,再將相應(yīng)的對象域(存儲對象的區(qū)域)返回給表示層,根據(jù)表示層在對象域之間的操作關(guān)系,持久層來導(dǎo)入相應(yīng)的對象。(也就是把session區(qū)域給表示層,然后分析它需要的對象,再讓持久層去加載這些對象)這就是所謂的lazy loading 技術(shù)。圖表6中顯示了表示層自由的訪問對象域的設(shè)計(jì)圖。


    Figure 6. Using an exposed domain model

    在圖表6的設(shè)計(jì)中,表示層不通過facade而直接調(diào)用域?qū)ο螅琒pring AOP仍然提供服務(wù),例如事務(wù)處理管理和安全。

    用這種實(shí)現(xiàn)途徑的一個(gè)重要的好處是,業(yè)務(wù)層不需要知道哪些對象需要調(diào)用,也不用知道那些需要返回給表示層。盡管這挺起來很簡單,但是你會發(fā)現(xiàn)一些缺點(diǎn)。這會增加表示層的復(fù)雜度,因?yàn)槟惚仨毺幚韺?shù)據(jù)庫的連接。而且在基于Web的應(yīng)用程序中,事務(wù)處理管理也要非常小心,因?yàn)樵诒硎緦訉?shù)據(jù)反饋給瀏覽器之前,事務(wù)處理的數(shù)據(jù)必須保持正確。

    決策3:訪問數(shù)據(jù)庫

    無論你怎樣對業(yè)務(wù)邏輯怎樣的組織和封裝,最終你還是要從數(shù)據(jù)庫中取數(shù)據(jù)出來。在經(jīng)典的J2EE應(yīng)用程序中,你有2個(gè)選擇:JDBC??這個(gè)需要很多的底層代碼;或者實(shí)體Bean??這個(gè)用起來非常困難,而且缺少重要特征。相比來說,使用輕量級構(gòu)架令人高興的事情之一就是:你有一些新的而且更有力的方法去訪問數(shù)據(jù)庫,而且這種方法可以顯著的減少訪問數(shù)據(jù)庫的代碼。讓咱們來進(jìn)一步研究

    直接用JDBC會有什么問題
    最近突然出現(xiàn)了對象/關(guān)系 映射構(gòu)架(比如JDO和Hibernate) 和SQL映射構(gòu)架(比如iBATIS)這些不是憑空出現(xiàn)的。相反,他們是在JAVA 聯(lián)盟在JDBC屢造挫折之后才出現(xiàn)的。為了了解新構(gòu)架出現(xiàn)的原因,這里咱們回顧一下直接使用JDBC會出現(xiàn)的問題。在許多程序中直接使用JDBC不是一個(gè)好的選擇,主要有以下三個(gè)原因:
    ?        開發(fā)和維護(hù)SQL非常的困難而且耗費(fèi)時(shí)間??一些開發(fā)者發(fā)現(xiàn)要寫龐大而且復(fù)雜的SQL語句非常的困難。反映數(shù)據(jù)庫變化的SQL語句會變得非常耗時(shí)。你必須小心的考慮犧牲可維護(hù)性是否值得。
    ?        用SQL會使移植性變的很差??因?yàn)樾枰獢?shù)據(jù)庫的特殊SQL語句。如果一個(gè)程序和多個(gè)數(shù)據(jù)庫有關(guān)系,那么你就要寫多個(gè)版本的SQL語句,這使得可維護(hù)性變變成噩夢。
    ?        直接寫JDBC代碼要會非常耗時(shí),而且容易出錯(cuò)。你必須寫很多的樣板代碼去獲得連接,創(chuàng)建和初始化適當(dāng)?shù)穆暶鳎€要用精確的聲明去清理連接。而且你還要寫代碼去將JAVA 對象映射到SQL聲明。由于要無奈的去寫,
    JDBC代碼很容易出錯(cuò)。

    如果你的程序必須直接運(yùn)行SQL語句的話,那前面兩個(gè)問題是無法避免的。有時(shí)候?yàn)榱双@得好的性能,必須要全力的寫SQL語句,包括供應(yīng)商提供的那些特殊東西。由于許多業(yè)務(wù)上的原因,持久層可能會產(chǎn)生混亂的SQL語句,為了防止這種情況,DBA可能要求你的程序來完全控制SQL語句的執(zhí)行。通常,團(tuán)隊(duì)買進(jìn)的關(guān)系型數(shù)據(jù)庫過于龐大,以至于應(yīng)用程序工作時(shí)會出現(xiàn)一些和數(shù)據(jù)庫有關(guān)的瑣碎事務(wù)。根據(jù)”iBATIS in Action”的作者說這里會有一種情況出現(xiàn):“數(shù)據(jù)庫或者SQL語句本身存在的時(shí)間比程序代碼存在的時(shí)間還要長,或者同一段SQL語句或數(shù)據(jù)庫有多個(gè)程序的版本。有些情況下,程序已經(jīng)用另外一種語言重寫了,但是SQL語句和數(shù)據(jù)庫卻沒有太大的改變。” 如果直接使用SQL弄的你筋疲力盡,那么很幸運(yùn),這里有一種直接執(zhí)行SQL語句的構(gòu)架,它可比用JDBC要容易多了。當(dāng)然了,這就是iBATIS.

    使用 iBATIS
    我開發(fā)過的所有企業(yè)JAVA應(yīng)用程序,都是直接執(zhí)行SQL語句的。早期的程序是執(zhí)行特定的SQL語句的,后來是用持久層構(gòu)架再用少量的SQL語句構(gòu)成的。一開始我直接用JDBC來執(zhí)行SQL語句,但是后來,我經(jīng)常寫一些小的構(gòu)架去完成JDBC中那些比較無聊的部分。我也用過一段Spring的JDBC類,這些類除去了JDBC中的許多樣板代碼。但是無論是我自己寫的構(gòu)架還是使用Spring的類,在Java類映射到SQL語句的時(shí)候都會存在問題,這就是我為什么那么高興的加入iTATIS 那邊的原因了。

    iBATIS 不僅將應(yīng)用程序完全的與“數(shù)據(jù)庫連接”、具體的SQL語句隔絕開來,更實(shí)現(xiàn)了通過XML描述文檔來將JavaBean 映射到SQL語句。它用Java bean 內(nèi)省機(jī)制來將“道具bean(bean properties)”映射為相應(yīng)的數(shù)據(jù)庫語句占位符,而且它可以將ResultSet后的結(jié)果構(gòu)造為bean。它還可以通過數(shù)據(jù)庫生成主鍵,自動(dòng)加載相關(guān)的對象、實(shí)現(xiàn)緩存和lazy loading。這樣,iBATIS 就除去了許多執(zhí)行SQL語句帶來的苦差。通過編輯XML描述文檔和調(diào)用少量的iBATIS的API,代替了寫大量的JDBC底層代碼。

    使用持久層框架
    當(dāng)然,iBATIS不能實(shí)現(xiàn)高層開發(fā)和維護(hù)SQL語句,而且缺乏可移植性。為了避免這類問題,你需要用到持久層框架。持久層框架可以將對象域映射到數(shù)據(jù)庫中。它提供了創(chuàng)建,查找,刪除對象的API函數(shù)。當(dāng)程序要控制對象時(shí)它可以自動(dòng)的加載相應(yīng)的對象,還可以在事務(wù)處理結(jié)束時(shí)自動(dòng)更新數(shù)據(jù)庫。持久層框架通過對象/關(guān)系映射機(jī)制可以自動(dòng)的生成SQL語句,對象/關(guān)系映射機(jī)制用XML文檔定義了怎樣將類映射為表,怎樣將數(shù)據(jù)映射為列(column)和關(guān)系是怎樣被映射為外鍵與連接表的。

    在持久層構(gòu)架上EJB也有它的短處:實(shí)體bean。EJB2的實(shí)體bean有很多的不足,而且開發(fā)和測試它會變得非常的枯燥。最后,很少用EJB2的實(shí)體bean了。在EJB3中會說明那些問題。

    兩種最有流行的輕量級持久層構(gòu)架是JDO和Hibernate,前者是Sun的標(biāo)準(zhǔn)框架,后者是開源工程。兩種框架都可以為POJO類提供持久層事務(wù)處理。你可以用POJO類來開發(fā)和測試你的業(yè)務(wù)邏輯,而不用擔(dān)心持久層的問題,這個(gè)時(shí)候它會將類映射到數(shù)據(jù)庫中的schema。另外,他們兩個(gè)都可以在服務(wù)器程序外部或者內(nèi)部,這樣可以進(jìn)一步降低開發(fā)難度。用Hibernate和JDO來進(jìn)行開發(fā)比用老的EJB2的實(shí)體bean要舒服的多。

    除了要決定怎樣訪問數(shù)據(jù)庫外,還要決定如何處理數(shù)據(jù)庫的并行處理問題。下面來看一下,為什么并行處理問題那么重要,同時(shí)看一下可實(shí)現(xiàn)的選項(xiàng)

    決策4:處理數(shù)據(jù)庫事務(wù)處理的并行問題

    差不多所有的企業(yè)應(yīng)用程序都需要多用戶和多個(gè)后臺進(jìn)程并行的更新數(shù)據(jù)庫。2個(gè)數(shù)據(jù)庫 處理事務(wù)同時(shí)訪問同時(shí)訪問同一個(gè)數(shù)據(jù)是很正常的,但是這種情況很可能引起數(shù)據(jù)庫中的數(shù)據(jù)不一致或者引起應(yīng)用程序的不正常。由于大部分的應(yīng)用程序都需要處理多個(gè)處理事務(wù)并行訪問同一個(gè)數(shù)據(jù),則它可以影響到業(yè)務(wù)和持久層的設(shè)計(jì)。

    無論你是使用EJB還是輕量級構(gòu)架,你的程序必須可以并行訪問共享數(shù)據(jù)。EJB2要求使用供應(yīng)商提供的特殊擴(kuò)充接口來實(shí)現(xiàn)并行,然而與此不同的是,JDO和Hibernate可以直接支持大部分并行機(jī)制。更重要的是,使用JDO和Hibernate不僅只配置簡單,而且只需要少量的代碼就可以實(shí)現(xiàn)了。

    在這樣主要介紹幾種“并行更新數(shù)據(jù)庫處理事務(wù)”的選項(xiàng)的概要,這些事務(wù)處理和用戶的輸入無關(guān)。下一章,我主要介紹一下如何在應(yīng)用程序級長時(shí)間的并行更新數(shù)據(jù)庫處理事務(wù),這種處理事務(wù)會與用戶輸入有關(guān),而且是由一系列的數(shù)據(jù)庫事務(wù)處理組成的。

    獨(dú)立數(shù)據(jù)庫事務(wù)
    有時(shí)候?qū)蚕頂?shù)據(jù)的并行訪問可以簡單的依靠數(shù)據(jù)庫本身來實(shí)現(xiàn),數(shù)據(jù)庫可以設(shè)置為執(zhí)行孤立的數(shù)據(jù)??這只是對數(shù)據(jù)庫而言。如果你對這種概念不熟悉也不要擔(dān)心,你只要記住:如果應(yīng)用程序使用完全的孤立事務(wù)方式,那么同時(shí)執(zhí)行2個(gè)事務(wù)的結(jié)果和一個(gè)接一個(gè)的執(zhí)行是一樣的。(也就是說,如果你用孤立事務(wù)的方式來訪問數(shù)據(jù)庫的話,你同時(shí)執(zhí)行2個(gè)事務(wù),就會變成一個(gè)接一個(gè)的串行執(zhí)行了。)

    這種方法也許聽起來非常的簡單,但問題是這種處理方式有時(shí)候會降低性能,因?yàn)槿绾螌?shí)現(xiàn)對事務(wù)的孤立是由數(shù)據(jù)庫來決定的。為了這個(gè)原因,許多應(yīng)用程序都避免使用它,而采用optimistic或者pessimistic 所鎖,這會在下面講到。

    開放式鎖定
    并行更新數(shù)據(jù)的一種途徑是用開放式鎖定。開放式鎖定工作原理是通過應(yīng)用程序來檢查數(shù)據(jù)是否被更新(被其他事務(wù)修改造成的)而實(shí)現(xiàn)的。一種更普通的實(shí)現(xiàn)開放式鎖定的方法是在每個(gè)表中添加一個(gè)“版本列”(version column),對每個(gè)表而言,程序每次改變其中一行的時(shí)候都會更新這個(gè)“版本列”。每個(gè)UPDATE語句中的WHERE語句會根據(jù)上次查詢的結(jié)果判斷這個(gè)版本號是不是被更改了。在事務(wù)訪問數(shù)據(jù)庫中的數(shù)據(jù)時(shí),程序中可以用PreparedStatement.executeUpadte()這個(gè)函數(shù)的返回值來檢查行的個(gè)數(shù),從而判斷是否要繼續(xù)執(zhí)行UPDATE語句。如果數(shù)據(jù)中的行已經(jīng)被其他的事務(wù)更新或者刪除了,那么程序會讓該事務(wù)從新訪問數(shù)據(jù)庫。

    用開放式鎖定機(jī)制來鎖定那些直接執(zhí)行SQL語句的應(yīng)用程序是非常簡單的。但是,用持久層構(gòu)架(比如JDO和Hibernate)實(shí)現(xiàn)更容易,因?yàn)樗麄円呀?jīng)提供了開放式鎖定機(jī)制??在配置選項(xiàng)中。一旦在配置選項(xiàng)中,選中了這種方式,持久層構(gòu)架會自動(dòng)的生成SQL的UPDATE語句來完成版本檢查的任務(wù)。開放式鎖定的名字來源于一種假設(shè)的情況,在這種情況下:并發(fā)更新的機(jī)會非常少,而且程序只能檢測、覆蓋這些數(shù)據(jù)而不能防止這種事情的發(fā)生。另外一種可選的途徑是用保守式鎖定,使用他的假設(shè)條件是:并發(fā)更新肯定會發(fā)生,而且必須被禁止。

    保守式鎖定
    對于開放式鎖定來說,另外一種途徑是使用保守式鎖定。當(dāng)一個(gè)事務(wù)讀取某些行的數(shù)據(jù)時(shí),他會對這些數(shù)據(jù)加鎖,這樣就防止其他的事務(wù)訪問這些數(shù)據(jù)了。具體的實(shí)現(xiàn)是需要數(shù)據(jù)庫支持的,然而不幸的是,不是所有的數(shù)據(jù)庫都支持保守式鎖定。如果你的數(shù)據(jù)庫支持話,那么你的應(yīng)用程序直接執(zhí)行SQL語句來實(shí)現(xiàn)保守式鎖定將非常容易。但是,可能你已經(jīng)猜到了,在程序中用JDO或者Hibernate來實(shí)現(xiàn)保守式鎖定更容易,JDO以配置選項(xiàng)的方式提供了保守式鎖定,而Hibernage提供了簡單的API實(shí)現(xiàn)鎖定對象。

    除了可以處理單個(gè)數(shù)據(jù)庫事務(wù)并行問題,常常你還需要處理多數(shù)據(jù)庫事務(wù)的并行問題。

    決策5:在長事務(wù)下處理并發(fā)訪問

    獨(dú)立事務(wù)、開放式鎖定、和保守式鎖定只能用在單個(gè)數(shù)據(jù)庫事務(wù)上的,然而,許多的程序需要 長時(shí)間的 在多個(gè)數(shù)據(jù)庫事務(wù)之間 讀取或者更新 共享數(shù)據(jù)。比如,有一種情況描述的是 怎樣實(shí)現(xiàn) 用戶編輯命令,這和很多的進(jìn)程有關(guān),這些進(jìn)程可能會運(yùn)行 很長的時(shí)間,而且它由 多個(gè)數(shù)據(jù)庫事務(wù)組成。因?yàn)閿?shù)據(jù)可能會被 一個(gè)數(shù)據(jù)庫事務(wù) 讀取,而又被 另外一個(gè)數(shù)據(jù)庫事務(wù) 修改了,那么程序必須對 共享數(shù)據(jù)的并發(fā)訪問 進(jìn)行不同的處理。這樣就必須使用 開放式鎖定設(shè)計(jì)模式或 者保守是鎖定設(shè)計(jì)模式,關(guān)于這兩種模式會在Fowler的 Patterns of Enterprise Application Architecutre中詳細(xì)介紹。

    開放式脫機(jī)鎖定模式
    一種選擇是開放式鎖定機(jī)制的擴(kuò)展,它會從第一次讀取數(shù)據(jù)開始,在編輯進(jìn)程執(zhí)行后檢查數(shù)據(jù)是否已經(jīng)被修改了。例如,你可以在數(shù)據(jù)庫的共享數(shù)據(jù)的表中使用版本號來實(shí)現(xiàn)。在編輯進(jìn)程開始的時(shí)候,程序?qū)姹咎柎鎯Φ綍挔顟B(tài)中,然后每次用戶要存儲數(shù)據(jù)時(shí),應(yīng)用程序都要進(jìn)行檢查,保證數(shù)據(jù)庫中的版本號和會話狀態(tài)中的版本號一致。
    因?yàn)殚_放式脫機(jī)鎖定模式只有在用戶進(jìn)行保存修改過的數(shù)據(jù)時(shí)才可以檢測,所以它只有在不成為客戶的累贅的時(shí)候,才可以很好的運(yùn)行。但如果情況是:客戶必須要撤銷幾個(gè)操作的話,那么就會因?yàn)檫@種鎖定模式而非常苦惱,那么更好的一種選擇是用保守式脫機(jī)鎖定。

    保守式脫機(jī)鎖定模式
    在編輯進(jìn)程開始時(shí),保守式脫機(jī)鎖定方式通過鎖定 共享數(shù)據(jù),來解決 多個(gè)數(shù)據(jù)庫事務(wù) 同時(shí)更新共享數(shù)據(jù)的問題,這樣,這個(gè)編輯進(jìn)程就可以防止 其他的用戶來修改數(shù)據(jù)了。這種方式和保守式鎖定機(jī)制一開始描述的很類似,但它是靠程序來實(shí)現(xiàn)的,而不是數(shù)據(jù)庫。因?yàn)橥粫r(shí)間內(nèi),只有有權(quán)利編輯共享數(shù)據(jù)的用戶,才有權(quán)利去保存這些修改
    posted @ 2006-03-15 11:15 MEYE 閱讀(449) | 評論 (0)編輯 收藏
    利用jdom實(shí)現(xiàn)讀取數(shù)據(jù)庫生成XML及讀取XML文件插入數(shù)據(jù)庫



    1.    
    首先是準(zhǔn)備開源包,到http://jdom.org.下載,當(dāng)前最新版本是jdom-1.0.zip。

    2.    
    然后將其解壓,并將build文件夾下的jdom.jar,將其拷貝到你的jdk安裝目錄的lib下面,也拷貝到j(luò)dk安裝目錄下的jre文件夾的lib的ext下,同時(shí)會將這個(gè)目錄添加到環(huán)境變量classpath下。如: d:/jdk1.4/jre/lib/ext/jdom.jar和d:/jdk1.4/lib/jdom.jar.另外要注意的問題就是你存放java文件的路徑也要加到classpath 中去,至于java的環(huán)境變量的設(shè)置我這里不做介紹。

    3.
    在這個(gè)實(shí)例中我用的數(shù)據(jù)庫是mysql,因?yàn)槭俏冶容^喜歡開源和免費(fèi)的東西,所以選擇它。至于具體的版本如下:
    mysqlcc-0.9.4-win32.zip //圖形控制界面
    mysql-5.0.0a-alpha-win.zip 
    mysql-connector-java-3.0.17-ga.zip //連接驅(qū)動(dòng)程序的jar包
    其實(shí)別的版本也可以。具體的安裝我這里就不說了,如果不了解就可以到goole里找一下相關(guān)資料就可以了:)
    首先來看我數(shù)據(jù)庫表的設(shè)計(jì):為了簡單起見我只創(chuàng)見了一個(gè)含有兩個(gè)表的數(shù)據(jù)庫jdomdb,其中一個(gè)表是存放用戶信息的userinfo表,另外一個(gè)就是用于存放演示中讀取xml文件后往數(shù)據(jù)庫里面插入的數(shù)據(jù)的表tmpinfo。
    下面開始創(chuàng)建數(shù)據(jù)庫表信息如下圖:
     

    左側(cè)部分就是表userinfo字段信息的。同時(shí)表tmpinfo的字段信息也是一樣。這里我也提供了數(shù)據(jù)庫的表結(jié)構(gòu)文件jdomdb.sql,你只要建立好名為jdomdb數(shù)據(jù)庫,然后將其導(dǎo)入就可以了。
    為了演示我們必須準(zhǔn)備基本的數(shù)據(jù),這里我們通過一個(gè)jsp文件testdb.jsp來插入一些數(shù)據(jù)。或則你可以直接手工在表中插入幾條數(shù)據(jù)。

    4. 下載包中的文件說明:

    讀數(shù)據(jù)庫并將數(shù)據(jù)導(dǎo)出到XML文件中的文件:ExtraXml.java 其中導(dǎo)出來的文件名叫userinfo.xml;
    讀XML文件并將數(shù)據(jù)插入數(shù)據(jù)庫的文件: ReadXml.java ; 
    封裝數(shù)據(jù)庫連接等操作的JavaBean文件:DBConn.java ;
    有個(gè)封裝好的例子就是ExtraXml3.java,只要調(diào)用javabean做相應(yīng)的調(diào)用就可以了。
    jdomdb.sql是我導(dǎo)出來的最基本的數(shù)據(jù)庫的表結(jié)構(gòu),可以直接導(dǎo)入。
    還有所必須用到的jdom.jar包。

    下載連接:附件:javaXML.rar(150K) 

    參考網(wǎng)上的相關(guān)資料:http://www.knowsky.com/3226.html

    posted @ 2006-03-15 11:14 MEYE 閱讀(583) | 評論 (0)編輯 收藏
    僅列出標(biāo)題
    共10頁: First 上一頁 2 3 4 5 6 7 8 9 10 
    主站蜘蛛池模板: 亚洲日本成本人观看| 狼色精品人妻在线视频免费| 黄色片网站在线免费观看| 在线观看黄片免费入口不卡| 国产无人区码卡二卡三卡免费| 免费成人午夜视频| 亚洲精品第五页中文字幕| 黄页免费视频播放在线播放| 51在线视频免费观看视频| 亚洲精品国精品久久99热| 亚洲人成电影网站| 十八禁在线观看视频播放免费| 成全影视免费观看大全二| 亚洲第一AAAAA片| 亚洲日韩在线中文字幕综合| 99视频免费观看| 亚洲精品专区在线观看| 亚洲中文字幕乱码AV波多JI| 久久国产乱子精品免费女| 免费无码又爽又刺激高潮| 亚洲男人第一av网站| 无遮挡免费一区二区三区| 久九九精品免费视频| 亚洲国产精品久久久天堂| 国产区图片区小说区亚洲区| 精品福利一区二区三区免费视频| 2048亚洲精品国产| 亚洲国产无线乱码在线观看| 最近中文字幕mv免费高清视频8| 国产亚洲人成网站在线观看| 日韩国产精品亚洲а∨天堂免| 五月婷婷在线免费观看| 亚洲日韩中文无码久久| 免费精品视频在线| 日本a级片免费看| 亚洲国产精品白丝在线观看| 免费a级毛片无码a∨免费软件| 内射无码专区久久亚洲| 亚洲色欲色欲www在线播放| 最刺激黄a大片免费网站| 国产aⅴ无码专区亚洲av|