posts - 495,  comments - 11,  trackbacks - 0
           

          在*.hbm.xml必須聲明的< generator>子元素是一個Java類的名字,用來為該持久化類的實例生成唯一的標識。

          < generator class="sequence"/>

          這是一個非常簡單的接口;某些應用程序可以選擇提供他們自己特定的實現。當然,Hibernate提供了很多內置的實現。下面是Generator子元素的一些內置生成器的快捷名字:

          increment(遞增)

          用于為long, short或者int類型生成唯一標識。只有在沒有其他進程往同一張表中插入數據時才能使用。 在集群下不要使用。

          identity

          對DB2,MySQL, MS SQL Server, Sybase和HypersonicSQL的內置標識字段提供支持。返回的標識符是long, short 或者int類型的。

          sequence (序列)

          在DB2,PostgreSQL, Oracle, SAP DB, McKoi中使用序列(sequence),而在Interbase中使用生成器(generator)。返回的標識符是long, short或者 int類型的。

          hilo (高低位)

          使用一個高/低位算法來高效的生成long, short或者 int類型的標識符。給定一個表和字段(默認分別是是hibernate_unique_key 和next_hi)作為高位值得來源。高/低位算法生成的標識符只在一個特定的數據庫中是唯一的。在使用JTA獲得的連接或者用戶自行提供的連接中,不要使用這種生成器。

          seqhilo(使用序列的高低位)

          使用一個高/低位算法來高效的生成long, short或者 int類型的標識符,給定一個數據庫序列(sequence)的名字。

          uuid.hex

          用一個128-bit的UUID算法生成字符串類型的標識符。在一個網絡中唯一(使用了IP地址)。UUID被編碼為一個32位16進制數字的字符串。

          uuid.string

          使用同樣的UUID算法。UUID被編碼為一個16個字符長的任意ASCII字符組成的字符串。不能使用在PostgreSQL數據庫中

          native(本地)

          根據底層數據庫的能力選擇identity, sequence 或者hilo中的一個。

          assigned(程序設置)

          讓應用程序在save()之前為對象分配一個標示符。

          foreign(外部引用)

          使用另外一個相關聯的對象的標識符。和< one-to-one>聯合一起使用。

          Generator子元素的用法:

          1. <??class name="onlyfun.caterpillar.User" table="USER">
          2. ???????????<??id name="id" type="string" unsaved-value="null">
          3. ???????????????<??column name="USER_ID"/>
          4. ???????????????<??generator class="uuid.hex"/>
          5. ???????????<?? /id>
          posted @ 2009-07-03 14:04 jadmin 閱讀(57) | 評論 (0)編輯 收藏

          在Hibernate中有三種狀態,對它的深入理解,才能更好的理解hibernate的運行機理,剛開始不太注意這些概念,后來發現它是重要的。對于理解hibernate,JVM和sql的關系有更好的理解。對于需要持久化的JAVA對象,在它的生命周期中有三種狀態,而且互相轉化。

          Hibernate三種狀態之一:臨時狀態(Transient):用new創建的對象,它沒有持久化,沒有處于Session中,處于此狀態的對象叫臨時對象;

          Hibernate三種狀態之二:持久化狀態(Persistent):已經持久化,加入到了Session緩存中。如通過hibernate語句保存的對象。處于此狀態的對象叫持久對象;

          Hibernate三種狀態之三:游離狀態(Detached):持久化對象脫離了Session的對象。如Session緩存被清空的對象。特點:已經持久化,但不在Session緩存中。處于此狀態的對象叫游離對象;

          Hibernate三種狀態中游離對象和臨時對象異同:

          兩者都不會被Session關聯,對象屬性和數據庫可能不一致;

          游離對象由持久化對象關閉Session而轉化而來,在內存中還有對象所以此時就變成游離狀態了;

          Hibernate和SQL的關系:

          在操作了hibernate的方法如save()等后,并沒有直接生成sql語句,去操作數據庫,而是把這些更新存入Session中,只有Session緩存要被更新時,底層的sql語句才能執行,數據存入數據庫;

          下面舉例說明:

          一,Session.save(user)運行機理。
          1,把User對象加入緩存中,使它變成持久化對象;
          2,選用映射文件指定的標識生成ID;
          3,在Session清理緩存時候執行:在底層生成一個insert sql語句,把對象存入數據庫;

          注意:在你執行Session.save(user)后,在Session清理緩存前,如果你修改user對象屬性值,那么最終存入數據庫的值將是最后修改的值;此過程中ID不能被修改;

          二,Session.delete(user)運行過程。
          如果user是持久化對象,則執行刪除操作,同樣底層數據庫的執行條件是:在Session清理緩存時候;
          如果user是游離對象:
          1,將user對象和Session關聯,使之成為持久化對象;
          2,然后按照user 是持久化對象的過程執行;

          posted @ 2009-07-03 14:00 jadmin 閱讀(53) | 評論 (0)編輯 收藏

          Hibernate訪問多個數據庫的設計思路:利用 Hibernate中config = new Configuration().configure(configFile);可以加載不同數據庫配置信息的原理,編寫一個數據庫操作類,再編寫一個數據庫管理程序[map],將加載的數據庫連接實例put早數據庫管理程序中,具體實現見下面:

          Hibernate訪問多個數據庫步驟一:hibernate配置文件

          localhost.cfg.xml

          1. < ?xml version="1.0" encoding="utf-8"?>
          2. < !DOCTYPE hibernate-configuration
          3. ???? PUBLIC "-//Hibernate/Hibernate Configuration DTD//EN"
          4. ???? "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
          5. < hibernate-configuration>
          6. ????< session-factory >
          7. ??< !-- local connection properties -->
          8. ??< property name="hibernate.connection.url">jdbc:mysql://localhost:3306/bookshop?zeroDateTimeBehavior=convertToNull< /property>
          9. ??< property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver< /property>
          10. ??< property name="hibernate.connection.username">root< /property>
          11. ??< property name="hibernate.connection.password">12345678< /property>
          12. ??< !-- property name="hibernate.connection.pool_size">< /property -->
          13. ??< !-- dialect for MySQL -->
          14. ????????< property name="dialect">org.hibernate.dialect.MySQLDialect< /property>
          15. ????????< property name="hibernate.show_sql">true< /property>
          16. ????????< property name="hibernate.transaction.factory_class">org.hibernate.transaction.JDBCTransactionFactory< /property>????????
          17. ????????< property name="hbm2ddl.auto">update< /property>
          18. ?????< mapping resource="org/jskyme/data/local/po/Shop.hbm.xml"/>
          19. ????< /session-factory>
          20. < /hibernate-configuration>

          data_server.cfg.xml

          1. < ?xml version="1.0" encoding="utf-8"?>
          2. < !DOCTYPE hibernate-configuration
          3. ???? PUBLIC "-//Hibernate/Hibernate Configuration DTD//EN"
          4. ???? "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
          5. < hibernate-configuration>
          6. ????< session-factory >
          7. ??< !-- local connection properties -->
          8. ??< property name="hibernate.connection.url">jdbc:mysql://192.168.0.10:3306/bookshop?zeroDateTimeBehavior=convertToNull< /property>
          9. ??< property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver< /property>
          10. ??< property name="hibernate.connection.username">root< /property>
          11. ??< property name="hibernate.connection.password">12345678< /property>
          12. ??< !-- property name="hibernate.connection.pool_size">< /property -->
          13. ??< !-- dialect for MySQL -->
          14. ????????< property name="dialect">org.hibernate.dialect.MySQLDialect< /property>
          15. ????????< property name="hibernate.show_sql">true< /property>
          16. ????????< property name="hibernate.transaction.factory_class">org.hibernate.transaction.JDBCTransactionFactory< /property>????????
          17. ????????< property name="hbm2ddl.auto">update< /property>
          18. ?????< mapping resource="org/jskyme/data/local/po/Shop.hbm.xml"/>
          19. ????< /session-factory>
          20. < /hibernate-configuration>

          Hibernate訪問多個數據庫步驟二:數據庫訪問類:

          數據庫管理類:DataBaseManager

          1. package org.jskyme.hibernate.util;
          2. import java.util.HashMap;
          3. public class DataBaseManager extends HashMap {
          4. private static final long serialVersionUID = 6491666983237498097L;
          5. private static DataBaseManager inst = new DataBaseManager();
          6. public static DataBaseManager getInst() {
          7. ??return inst;
          8. }
          9. public SessionManager get(Object key) {
          10. ??return (SessionManager) super.get(key);
          11. }
          12. @Override
          13. public Object put(Object key, Object value) {
          14. ??return super.put(key, value);
          15. }
          16. public static void setInst(DataBaseManager inst) {
          17. ?? DataBaseManager.inst = inst;
          18. }
          19. }

          Hibernate連接數據庫操作類:

          1. package org.jskyme.hibernate.util;
          2. import java.util.List;
          3. import org.hibernate.Criteria;
          4. import org.hibernate.Query;
          5. import org.hibernate.SQLQuery;
          6. import org.hibernate.Session;
          7. import org.hibernate.SessionFactory;
          8. import org.hibernate.Transaction;
          9. import org.hibernate.cfg.Configuration;
          10. public final class SessionManager {
          11. private Configuration config;
          12. private SessionFactory sessionFactory;
          13. private Session session;
          14. public Criteria createCriteria(Class persistentClass) {
          15. ??return session.createCriteria(persistentClass);
          16. }
          17. private void buildSession() {
          18. ?? sessionFactory = config.buildSessionFactory();
          19. ?? session = sessionFactory.openSession();
          20. }
          21. public SessionManager(String configFile) {
          22. ?? config = new Configuration().configure(configFile);
          23. ?? buildSession();
          24. }
          25. public Session getSession() {
          26. ??return session;
          27. }
          28. public void save(Object obj) {
          29. ?? Transaction tx = session.beginTransaction();
          30. ?? session.save(obj);
          31. ?? tx.commit();
          32. }
          33. public Object load(Class clas, Integer priId) {
          34. ??return session.get(clas, priId);
          35. }
          36. public Query findbyhql(String hql) {
          37. ??return session.createQuery(hql);
          38. }
          39. public List pageSizeByhql(String hql) {
          40. ??return findbyhql(hql).list();
          41. }
          42. public SQLQuery findbysql(String sql) {
          43. ??return session.createSQLQuery(sql);
          44. }
          45. public void update(Object obj) {
          46. ?? Transaction tx = session.beginTransaction();
          47. ?? session.saveOrUpdate(obj);
          48. ?? tx.commit();
          49. }
          50. public void delete(Class clas, Integer inte) {
          51. ?? session.delete(load(clas, inte));
          52. }
          53. public void delete(Object obj) {
          54. ?? session.delete(obj);
          55. }
          56. public void deletebyhql(String hql) {
          57. ?? Query query = session.createQuery(hql);
          58. ?? query.executeUpdate();
          59. }
          60. public Query createQuery(String hql) {
          61. ??return session.createQuery(hql);
          62. }
          63. }

          Hibernate訪問多個數據庫步驟三:測試類

          1. package org.jskyme.data.test;
          2. import junit.framework.TestCase;
          3. import org.hibernate.Query;
          4. import org.jskyme.hibernate.util.DataBaseManager;
          5. import org.jskyme.hibernate.util.SessionManager;
          6. public class DataBaseManagerTest extends TestCase {
          7. DataBaseManager dbm = DataBaseManager.getInst();
          8. public void testDatabase() {
          9. ?? setDatabase();
          10. ?? SessionManager tempSess = dbm.get("dataLocal");
          11. ?? Query query = tempSess.createQuery("from?? Shop");
          12. ?? query.list();
          13. ??
          14. ?? SessionManager tempSess27 = dbm.get("dateManage");
          15. ?? Query query27 = tempSess27.createQuery("from Shop");
          16. ?? query27.list();
          17. }
          18. private void setDatabase() {
          19. ?? SessionManager dateManageLocal = new SessionManager("localhost.cfg.xml");
          20. ?? SessionManager dateManage27 = new SessionManager("data_server.cfg.xml");
          21. ?? dbm.put("dateManage", dateManage27);
          22. ?? dbm.put("dataLocal", dateManageLocal);
          23. }
          24. }
          posted @ 2009-07-03 13:51 jadmin 閱讀(73) | 評論 (0)編輯 收藏

          Hibernate延時加載,其實這個異常寫的非常之清楚,就是會話關閉,無法對Hibernate實體進行操作。造成這樣的情況有很多,什么書寫錯誤啊,邏輯錯誤啊。

          但就此說一下關于lazy機制:

          Hibernate延時加載包括延遲初始化錯誤,這是運用Hibernate開發項目時最常見的錯誤。如果對一個類或者集合配置了延遲檢索策略,那么必須當代理類實例或代理集合處于持久化狀態(即處于Session范圍內)時,才能初始化它。如果在游離狀態時才初始化它,就會產生延遲初始化錯誤。

          下面把Customer.hbm.xml文件的< class>元素的lazy屬性設為true,表示使用延遲檢索策略:

          1. < class name="mypack.Customer" table="CUSTOMERS" lazy="true">??

          當執行Session的load()方法時,Hibernate不會立即執行查詢CUSTOMERS表的select語句,僅僅返回Customer類的代理類的實例,這個代理類具由以下特征:

          (1) 由Hibernate在運行時動態生成,它擴展了Customer類,因此它繼承了Customer類的所有屬性和方法,但它的實現對于應用程序是透明的。

          (2) 當Hibernate創建Customer代理類實例時,僅僅初始化了它的OID屬性,其他屬性都為null,因此這個代理類實例占用的內存很少。

          (3)當應用程序第一次訪問Customer代理類實例時(例如調用customer.getXXX()或customer.setXXX ()方法), Hibernate會初始化代理類實例,在初始化過程中執行select語句,真正從數據庫中加載Customer對象的所有數據。但有個例外,那就是當 應用程序訪問Customer代理類實例的getId()方法時,Hibernate不會初始化代理類實例,因為在創建代理類實例時OID就存在了,不必 到數據庫中去查詢。

          提示:Hibernate采用CGLIB工具來生成持久化類的代理類。CGLIB是一個功能強大的Java字節碼生成工具,它能夠在程序運行時動態生成擴 展 Java類或者實現Java接口的代理類。

          以下代碼先通過Session的load()方法加載Customer對象,然后訪問它的name屬性:

          1. tx = session.beginTransaction();
          2. Customer customer=(Customer)session.load(Customer.class,new Long(1));
          3. customer.getName();
          4. tx.commit();??

          在運行session.load ()方 法時Hibernate不執行任何select語句,僅僅返回Customer類的代理類的實例,它的OID為1,這是由load()方法的第二個 參數指定的。當應用程序調用customer.getName()方法時,Hibernate會初始化Customer代理類實例,從數據庫中加載 Customer對象的數據,執行以下select語句:

          1. select * from CUSTOMERS where ID=1;
          2. select * from ORDERS where CUSTOMER_ID=1;??

          當< class>元素的lazy屬性為true,會影響Session的load()方法的各種運行時行為,下面舉例說明。

          1.如果加載的Customer對象在數據庫中不存在,Session的load()方法不會拋出異常,只有當運行customer.getName()方法時才會拋出以下異常:

          1. ERROR LazyInitializer:63 - Exception initializing proxy
          2. net.sf.hibernate.ObjectNotFoundException: No row with the given identifier exists: 1, of class:
          3. mypack.Customer??

          2.如果在整個Session范圍內,應用程序沒有訪問過Customer對象,那么Customer代理類的實例一直不會被初始化,Hibernate不會執行任何select語句。以下代碼試圖在關閉Session后訪問Customer游離對象:

          1. tx = session.beginTransaction();
          2. Customer customer=(Customer)session.load(Customer.class,new Long(1));
          3. tx.commit();
          4. session.close();
          5. customer.getName();??

          由于引用變量customer引用的Customer代理類的實例在Session范圍內始終沒有被初始化,因此在執行customer.getName()方法時,Hibernate會拋出以下異常(Hibernate延時加載的問題之一):

          1. ERROR LazyInitializer:63 - Exception initializing proxy
          2. net.sf.hibernate.HibernateException: Couldnotinitializeproxy-theowningSessionwasclosed??

          由此可見,Customer代理類的實例只有在當前Session范圍內才能被初始化。

          3.net.sf.hibernate.Hibernate類的initialize()靜態方法用于在Session范圍內顯式初始化代理類實例,isInitialized()方法用于判斷代理類實例是否已經被初始化。例如:

          1. tx = session.beginTransaction();
          2. Customer customer=(Customer)session.load(Customer.class,new Long(1));
          3. if(!Hibernate.isInitialized(customer))
          4. Hibernate.initialize(customer);
          5. tx.commit();
          6. session.close();
          7. customer.getName();??

          以上代碼在Session范圍內通過Hibernate類的initialize()方法顯式初始化了Customer代理類實例,因此當Session關閉后,可以正常訪問Customer游離對象。

          4.當應用程序訪問代理類實例的getId()方法時,不會觸發Hibernate初始化代理類實例的行為,例如:

          1. tx = session.beginTransaction();
          2. Customer customer=(Customer)session.load(Customer.class,new Long(1));
          3. customer.getId();
          4. tx.commit();
          5. session.close();
          6. customer.getName();??

          當應用程序訪問customer.getId()方法時,該方法直接返回Customer代理類實例的OID值,無需查詢數據庫。由于引用變量 customer始終引用的是沒有被初始化的Customer代理類實例,因此當Session關閉后再執行customer.getName()方法, Hibernate會拋出以下異常(Hibernate延時加載的問題之一):

          1. ERROR LazyInitializer:63 - Exception initializing proxy
          2. net.sf.hibernate.HibernateException: Couldnotinitializeproxy-theowningSessionwasclosed??

          解決方法:

          由于hibernate采用了lazy=true,這樣當你用hibernate查詢時,返回實際為利用cglib增強的代理類,但其并沒有實際填 充;當你在前端,利用它來取值(getXXX)時,這時Hibernate才會到數據庫執行查詢,并填充對象,但此時如果和這個代理類相關的session已關閉掉,就會產生種錯誤.

          在做一對多時,有時會出現"could not initialize proxy - clothe owning Session was sed,這個好像是hibernate的緩存問題.問題解決:需要在< many-to-one>里設置lazy="false". 但有可能會引發另一個異常叫

          1. failed to lazily initialize a collection of role: XXXXXXXX, no session or session was closed??

          解決方法:在web.xml中加入

          1. < filter>
          2. ????< filter-name>hibernateFilter< /filter-name>
          3. ????< filter-class>
          4. ????? org.springframework.orm.hibernate3.support.OpenSessionInViewFilter
          5. ????< /filter-class>
          6. < /filter>
          7. < filter-mapping>
          8. ????< filter-name>hibernateFilter< /filter-name>
          9. ????< url-pattern>*.do< /url-pattern>
          10. < /filter-mapping>

          就可以了。

          以上文章轉自:http://developer.51cto.com/art/200907/133249.htm

          關鍵字:Hibernate,延時加載,lazy

          posted @ 2009-07-03 13:39 jadmin 閱讀(82) | 評論 (0)編輯 收藏
          眾所周知,設計模式描述的就是針對軟件設計中的常見問題做出的可重復使用的解決方案。而了解及使用這些模式則是SOA取得成功的根本。
          企業軟件熱點文章
          Windows 7與Vista價格對比 微軟大幅延長Windows 7 降級XP期限
          Windows 7完整公開發售路線圖 微軟推Windows 7選擇升級計劃 VAIO率先響應
          微軟稱Windows 7限期打折 預定只須50美元 Windows 7免費升級計劃截至2010年1月31日
          歐洲用戶不能升級Windows 7 只能全新安裝 消息稱Windows 7中國零售價最低399元起

          眾所周知,設計模式描述的就是針對軟件設計中的常見問題做出的可重復使用的解決方案。而了解及使用這些模式則是SOA取得成功的根本。下面是Gartner公司的分析師們通過分析得出的五種新興SOA設計模式:

          1. 多通道應用

          2. 復合應用

          3. 業務流程編排

          4. 面向服務的企業

          5. 聯邦SOA

          多通道應用

          用SOA實現多通道應用真是再合適不過。這種模式能將后端業務邏輯與前端邏輯分離,通過各個通道在最短的時間內將全部的應用功能提交到最大數量的用戶手上,并能重復使用同一服務。

          戰略遠景:2008年,將有超過66%的新開發的中到大型交互式應用軟件是支持多通道訪問的,而2007年這一數據尚不及33%。

          復合應用

          在復合應用中使用的服務可能是新部署的服務、經過調整和封裝的舊應用組件、或者是以上兩者的組合。在組合SOA環境中,有兩種集成技術是使系統有效運行的關鍵:1)幫助用戶封裝并接受各種初始SOA應用的服務接口底層的集成技術;和2)幫助用戶組裝并監控服務操作的集成技術。

          戰略遠景:到2012年,大部分SOA應用軟件將是交互式的復合應用。

          業務流程編排

          業務流程管理(BPM)軟件包是用來實現基于SOA的多步處理過程的工具。BPEL標準經常被用來描述所設計的元數據流模型。元數據庫(meta-database)是用來在運行時管理這些業務過程模型的行為的。這些過程中的部分步驟是通過調用SOA服務實現的。其它的步驟則需要人為的干預。

          戰略遠景:到2009年,有超過75%的SOA應用將通過外部BPM技術實現一部分與服務部署無關的順序控制。

          面向服務的企業

          基于SOA的企業模型離復合應用只有一步之遙。在這里,所有的應用程序都被看作是整體的一個組成部分。沒有任何新應用程序是獨立創建的。所有的應用程序都是以可重用的組件為基礎構建的,它們不但可以實現預期的功能,也可以在其它環境下被不同的客戶端使用。從本質上說,綜合式的復合企業所擁有的已不是應用程序,而是業務組件——每一個組件都是企業的資產。

          戰略遠景:到2010年,超過85%的企業會把應用集成視為與SOA管理工具和組織同樣的企業組件。

          聯邦SOA

          聯邦SOA的基本概念就是采用合理的程序將企業分解為半獨立的SOA領域(比如,以子公司、業務單元或部門來表示企業組織),每個領域都有其獨自特有的SOA基礎設施、治理過程和SOA卓越中心。然后各領域通過合適的互用性基礎設施、治理過程和組織方式形成聯邦(即以聯合的方式實現領域內的服務共享,這是通常的方式,但不是必須的方式)。“SOA聯邦”即是通過適當的技術、治理和組織方式形成聯邦式SOA的過程。

          戰略遠景:很少有大型組織有能力獨自做出整個IT的宏偉藍圖。最好的實踐還是支持領域的獨立性并允許使用不同的技術與架構以換取互操作性協議與傳輸的同步。合并與收購很顯然就是聯邦SOA的一種方式。

          posted @ 2009-06-28 13:25 jadmin 閱讀(67) | 評論 (0)編輯 收藏
            許多種類的錯誤將觸發異常,這些問題從像硬盤(crash)墜毀這樣的嚴重硬件錯誤,到嘗試訪問越界數組元素這樣的簡單程序錯誤,像這樣的錯誤如果在java函數中發生,函數將創建一個異常對象并把他拋出到運行時系統(runtimesystem)。

            許多種類的錯誤將觸發異常,這些問題從像硬盤(crash)墜毀這樣的嚴重硬件錯誤,到嘗試訪問越界數組元素這樣的簡單程序錯誤,像這樣的錯誤如果在java函數中發生,函數將創建一個異常對象并把他拋出到運行時系統(runtimesystem)。異常對象包含異常的信息,包括異常的類型,異常發生時程序的狀態。運行時系統則有責任找到一些代碼處理這個錯誤。在java技術詞典中,創建一個異常對象并把它拋給運行時系統叫做:拋出異常(throwinganexception)。

            當某個函數拋出一個異常后,運行時系統跳入了這樣一個動作,就是找到一些人(譯者注:其實是代碼)來處理這個異常。要找的處理異常的可能的人(代碼)的集合(set)是:在發生異常的方法的調用堆棧(callstack)中的方法的集合(set)。運行時系統向后搜尋調用堆棧,從錯誤發生的函數,一直到找到一個包括合適的異常處理器(exceptionhandler)的函數。一個異常處理器是否合適取決于拋出的異常是否和異常處理器處理的異常是同一種類型。因而異常向后尋找整個調用堆棧,直到一個合格的異常處理器被找到,調用函數處理這個異常。異常處理器的選擇被叫做:捕獲異常(catchtheexception)。

            如果運行時系統搜尋整個調用堆棧都沒有找到合適的異常處理器,運行時系統將結束,隨之java程序也將結束。

            使用異常來管理錯誤,比傳統的錯誤管理技術有如下優勢:

            1. 將錯誤處理代碼于正常的代碼分開。

            2. 沿著調用堆棧向上傳遞錯誤。

            3. 將錯誤分作,并區分錯誤類型。

            1. 將錯誤處理代碼于正常的代碼分開。

            在傳統的程序種,錯誤偵測,報告,和處理,經常導致令人迷惑的意大利面條式(spaghetti)的代碼。例如,假設你要寫一個將這個文件讀到內存種的函數,用偽代碼描述,你的函數應該是這個樣子的:

            readFile

            open the file; //打開文件

            determine its size; //取得文件的大小

            allocate that much memory; //分配內存

            read the file into memory; //讀文件內容到內存中

            close the file; //關閉文件

            匆匆一看,這個版本是足夠的簡單,但是它忽略了所有潛在的問題:

            n 文件不能打開將發生什么?

            n 文件大小不能取得將發生什么?

            n 沒有足夠的內存分配將發生什么?

            n 讀取失敗將發生什么?

            n 文件不能關閉將發生什么?

            為了在read_file函數中回答這些錯誤,你不得不加大量的代碼進行錯誤偵測,報告和處理,你的函數最后將看起來像這個樣子:

            errorCodeType readFile

            initialize errorCode = 0;

            open the file;

            if (theFileIsOpen)

            determine the length of the file;

            if (gotTheFileLength)

            allocate that much memory;

            if (gotEnoughMemory)

            read the file into memory;

            if (readFailed)

            errorCode = -1;

            else

            errorCode = -2;

            else

            errorCode = -3;

            close the file;

            if (theFileDidntClose && errorCode 0)

            errorCode = -4;

            else

            errorCode = errorCode and -4;

            else

            errorCode = -5;

            return errorCode;

            隨著錯誤偵測的建立,你的最初的7行代碼(粗體)已經迅速的膨脹到了29行-幾乎400%的膨脹率。更糟糕的是有這樣的錯誤偵測,報告和錯誤返回值,使得最初有意義的7行代碼淹沒在混亂之中,代碼的邏輯流程也被淹沒。很難回答代碼是否做的正確的事情:如果函數分配內容失敗,文件真的將被關閉嗎?更難確定當你在三個月后再次修改代碼,它是否還能夠正確的執行。許多程序員“解決”這個問題的方法是簡單的忽略它,那樣錯誤將以死機來報告自己。

            對于錯誤管理,Java提供一種優雅的解決方案:異常。異常可以使你代碼中的主流程和處理異常情況的代碼分開。如果你用異常代替傳統的錯誤管理技術,readFile函數將像這個樣子:

            readFile

            try

            open the file;

            determine its size;

            allocate that much memory;

            read the file into memory;

            close the file;

            catch (fileOpenFailed)

            doSomething;

            catch (sizeDeterminationFailed)

            doSomething;

            catch (memoryAllocationFailed)

            doSomething;

            catch (readFailed)

            doSomething;

            catch (fileCloseFailed)

            doSomething;

            注意:異常并不能節省你偵測,報告和處理錯誤的努力。異常提供給你的是:當一些不正常的事情發生時,將所有蹩腳(grungy)的細節,從你的程序主邏輯流程中分開。

            另外,異常錯誤管理的膨脹系數大概是250%,比傳統的錯誤處理技術的400%少的多。

          tags:異常

          posted @ 2009-06-25 23:45 jadmin 閱讀(80) | 評論 (0)編輯 收藏

          ?????? MD5的全稱是Message-Digest Algorithm 5,在90年代初由MIT的計算機科學實驗室和RSA Data Security Inc發明,經MD2、MD3和MD4發展而來。

          ?????? Message-Digest泛指字節串(Message)的Hash變換,就是把一個任意長度的字節串變換成一定長的大整數。請注意我使用了“字節串”而不是“字符串”這個詞,是因為這種變換只與字節的值有關,與字符集或編碼方式無關。

          ?????? MD5將任意長度的“字節串”變換成一個128bit的大整數,并且它是一個不可逆的字符串變換算法,換句話說就是,即使你看到源程序和算法描述,也無法將一個MD5的值變換回原始的字符串,從數學原理上說,是因為原始的字符串有無窮多個,這有點象不存在反函數的數學函數。

          ?????? MD5的典型應用是對一段Message(字節串)產生fingerprint(指紋),以防止被“篡改”。舉個例子,你將一段話寫在一個叫 readme.txt文件中,并對這個readme.txt產生一個MD5的值并記錄在案,然后你可以傳播這個文件給別人,別人如果修改了文件中的任何內容,你對這個文件重新計算MD5時就會發現(兩個MD5值不相同)。如果再有一個第三方的認證機構,用MD5還可以防止文件作者的“抵賴”,這就是所謂的數字簽名應用。

          ?????? MD5還廣泛用于加密和解密技術上,在很多操作系統中,用戶的密碼是以MD5值(或類似的其它算法)的方式保存的, 用戶Login的時候,系統是把用戶輸入的密碼計算成MD5值,然后再去和系統中保存的MD5值進行比較,而系統并不“知道”用戶的密碼是什么。

          ?????? 關鍵詞:MD5,MD5算法,文件的MD5值,文件 | 曦勤,[風故故,也依依], 博客,百度,IT

          posted @ 2009-05-28 19:45 jadmin 閱讀(111) | 評論 (0)編輯 收藏

          代碼如下:

          /*
          * @(#)DatabaseBackup.java Apr 23, 2009
          *
          * Copyright (c) 2009 by jadmin. All Rights Reserved.
          */

          package util.dbak;

          import java.io.BufferedReader;
          import java.io.File;
          import java.io.FileInputStream;
          import java.io.FileNotFoundException;
          import java.io.FileOutputStream;
          import java.io.IOException;
          import java.io.InputStream;
          import java.io.InputStreamReader;
          import java.io.OutputStream;
          import java.io.OutputStreamWriter;
          import java.io.PrintWriter;
          import java.io.UnsupportedEncodingException;

          /**
          * MySQL數據庫的備份與恢復
          * 缺陷:可能會被殺毒軟件攔截
          *
          * @author <a href="mailto:jadmin@163.com">jadmin</a>
          * @version $Revision: 1.0 Apr 23, 2009 11:44:00 PM $
          */
          public class DatabaseBackup {

          /** MySQL安裝目錄的Bin目錄的絕對路徑 */
          private String mysqlBinPath;

          /** 訪問MySQL數據庫的用戶名 */
          private String username;

          /** 訪問MySQL數據庫的密碼 */
          private String password;

          public String getMysqlBinPath() {
          ?? return mysqlBinPath;
          }

          public void setMysqlBinPath(String mysqlBinPath) {
          ?? this.mysqlBinPath = mysqlBinPath;
          }

          public String getUsername() {
          ?? return username;
          }

          public void setUsername(String username) {
          ?? this.username = username;
          }

          public String getPassword() {
          ?? return password;
          }

          public void setPassword(String password) {
          ?? this.password = password;
          }

          public DatabaseBackup() {
          ?? super();
          }

          public DatabaseBackup(String mysqlBinPath, String username, String password) {
          ?? super();
          ?? if (!mysqlBinPath.endsWith(File.separator)) {
          ??? mysqlBinPath = mysqlBinPath + File.separator;
          ?? }
          ?? this.mysqlBinPath = mysqlBinPath;
          ?? this.username = username;
          ?? this.password = password;
          }

          /**
          * 備份數據庫
          *
          * @param output 輸出流
          * @param dbname 要備份的數據庫名
          */
          public void backup(OutputStream output, String dbname) {
          ?? String command = "cmd /c " + mysqlBinPath + "mysqldump -u" + username + " -p" + password + " --set-charset=utf8 "
          ???? + dbname;
          ?? System.out.println(command);
          ?? PrintWriter p = null;
          ?? BufferedReader reader = null;
          ?? try {
          ??? p = new PrintWriter(new OutputStreamWriter(output, "utf8"));
          ??? Process process = Runtime.getRuntime().exec(command);
          ??? InputStreamReader inputStreamReader = new InputStreamReader(process.getInputStream(), "utf8");
          ??? reader = new BufferedReader(inputStreamReader);
          ??? String line = null;
          ??? while ((line = reader.readLine()) != null) {
          ???? p.println(line);
          ??? }
          ??? p.flush();
          ?? } catch (UnsupportedEncodingException e) {
          ??? e.printStackTrace();
          ?? } catch (IOException e) {
          ??? e.printStackTrace();
          ?? } finally {
          ??? try {
          ???? if (reader != null) {
          ????? reader.close();
          ???? }
          ???? if (p != null) {
          ????? p.close();
          ???? }
          ??? } catch (IOException e) {
          ???? e.printStackTrace();
          ??? }
          ?? }
          }

          /**
          * 備份數據庫,如果指定路徑的文件不存在會自動生成
          *
          * @param dest 備份文件的路徑
          * @param dbname 要備份的數據庫
          */
          public void backup(String dest, String dbname) {
          ?? try {
          ??? OutputStream out = new FileOutputStream(dest);
          ??? backup(out, dbname);
          ?? } catch (FileNotFoundException e) {
          ??? e.printStackTrace();
          ?? }
          }

          /**
          * 恢復數據庫
          *
          * @param input 輸入流
          * @param dbname 數據庫名
          */
          public void restore(InputStream input, String dbname) {
          ?? String command = "cmd /c " + mysqlBinPath + "mysql -u" + username + " -p" + password + " " + dbname;
          ?? try {
          ??? Process process = Runtime.getRuntime().exec(command);
          ??? OutputStream out = process.getOutputStream();
          ??? String line = null;
          ??? String outStr = null;
          ??? StringBuffer sb = new StringBuffer("");
          ??? BufferedReader br = new BufferedReader(new InputStreamReader(input, "utf8"));
          ??? while ((line = br.readLine()) != null) {
          ???? sb.append(line + "\r\n");
          ??? }
          ??? outStr = sb.toString();

          ??? OutputStreamWriter writer = new OutputStreamWriter(out, "utf8");
          ??? writer.write(outStr);
          ??? writer.flush();
          ??? out.close();
          ??? br.close();
          ??? writer.close();
          ?? } catch (UnsupportedEncodingException e) {
          ??? e.printStackTrace();
          ?? } catch (IOException e) {
          ??? e.printStackTrace();
          ?? }

          }

          /**
          * 恢復數據庫
          *
          * @param dest 備份文件的路徑
          * @param dbname 數據庫名
          */
          public void restore(String dest, String dbname) {
          ?? try {
          ??? InputStream input = new FileInputStream(dest);
          ??? restore(input, dbname);
          ?? } catch (FileNotFoundException e) {
          ??? e.printStackTrace();
          ?? }
          }

          public static void main(String[] args) {
          ?? DatabaseBackup bak = new DatabaseBackup("C:/MySQL/UTF8/bin", "root", "root");
          ?? bak.restore("c:/t.sql", "ttk");
          }
          }

          tags:java,mysql,database,數據庫,備份,恢復,mysql命令

          posted @ 2009-04-24 22:55 jadmin 閱讀(89) | 評論 (0)編輯 收藏

          在實際項目中,經常會遇到這樣的問題:想得到某個目錄下的所有具有特定擴展名文件的文件名集合

          解決方法:

          1.定義自己的文件名過濾器類,這個類必須實現java.io.FilenameFilter接口

          2.調用


          下面是我的一個例子,目標:得到目錄Constans.SCRIPT_DIR下所有擴展名為".sql"的文件的文件名集合

          1.實現自己的文件名過濾類

          /**
          * 腳本文件過濾器
          *
          * @author <a href="mailto:jadmin@126.com">jadmin</a>
          */
          public class ScriptFilenameFilter implements FilenameFilter {

          private String suffix;

          public ScriptFilenameFilter(String suffix) {
          ?? this.suffix = suffix;
          }

          public boolean accept(File dir, String name) {
          ?? if(name.endsWith(suffix)) {
          ??? return true;
          ?? }
          ?? return false;
          }

          }


          2.調用

          String[] names = new java.io.File(Constans.SCRIPT_DIR).list(new ScriptFilenameFilter(".sql"));

          這樣就得到了一個文件名數組,注:Constans.SCRIPT_DIR是【目錄】常量串

          posted @ 2009-01-16 21:56 jadmin 閱讀(97) | 評論 (0)編輯 收藏

          使用筆記本,避免不了經常變換IP,如果是手動去每次都設置,太煩人了,下面推薦一款實用的綠色IP切換工具IPWhiz,使用起來非常方便,下面是截圖:

          PS:之前一直使用的是ASUS的公用程序Net4Switch,其實這一款也是很好用的IP切換工具,只不過我的瑞星更新到2009版后Net4Switch就出問題了,可能是軟件之間沖突了吧...

          posted @ 2008-12-30 20:38 jadmin 閱讀(64) | 評論 (0)編輯 收藏
          僅列出標題
          共50頁: First 上一頁 14 15 16 17 18 19 20 21 22 下一頁 Last 
          主站蜘蛛池模板: 工布江达县| 漳州市| 松江区| 盈江县| 台南市| 凤冈县| 永德县| 杂多县| 陆川县| 沂南县| 嘉鱼县| 砚山县| 永德县| 若尔盖县| 饶平县| 颍上县| 星子县| 崇礼县| 罗甸县| 嘉兴市| 衡水市| 茂名市| 杨浦区| 井研县| 普陀区| 仪陇县| 锦州市| 通城县| 从江县| 大港区| 滨海县| 申扎县| 广西| 如东县| 岑巩县| 依兰县| 嘉禾县| 安乡县| 资兴市| 绍兴市| 新巴尔虎右旗|