字符串的聲明和初始化主要有如下兩種狀況:java
1:對於String s1 = new String("abc")語句與String s2 = new String("abc")語句,存在兩個引用對象s1,s2,兩個內容相同的字符串對象「abc」,它們在內存中的地址是不同的。只要用到new總會生成新的對象。web
2:對於String s1 = "abc"與String s2 = "abc"語句,在JVM中存在着一個字符串池,其中保存着不少String對象,而且能夠被共享使用,s1,s2引用的是同一個常量池的對象。因爲String的實現採用了Flyweight的設計模式,當建立一個字符串常量時,例如String s = "abc",會首先在字符串常量池中差最後啊是否已有相同的字符串被定義,其判斷依據是String類equals(Object obj)方法的返回值。若已經定義,則直接獲取對其的引用,此時不須要建立新的對象;若沒有定義,則首先建立這個對象,而後把它加入到字符串池中,再將它的引用返回。因爲String是不可變類,一旦建立好了就不能被修改,所以String對象能夠被共享並且不會致使程序的混亂。算法
1:「==」運算符用來比較兩個變量的值是否相等。該運算符用於比較變量對應的內存中所存儲的數值是否相同,要比較兩個基本類型的數據或兩個引用變量是否相等,只能使用「==」運算符。sql
2:equals是Object類提供的方法之一。每個java類都繼承自Object類,因此每個對象都具備equals這個方法。Object類中定義的equals(Object)方法是直接使用「==」運算符比較的兩個對象,因此在沒有覆蓋equals(Object)方法的狀況下,equals(Object)與「==」運算符同樣,比較的是引用。數據庫
相比「==」運算符,equals(Object)方法的特殊之處就在於它能夠被覆蓋,因此能夠經過覆蓋的方法讓他不是比較引用而是比較數據內容,例如String類的equals方法是用於比較兩個獨立對象的內容是否相同,即堆中的內容是否相同。編程
3:HashCode()方法是從Object類中繼承過來的。它返回對象在內存中地址轉換成的一個int值,因此若是沒有重寫hashcode()方法,任何對象的hashCode()方法都是不相等的。設計模式
hashCode方法與equals方法的關係以下:若是x.equals(y)返回true,那麼調用這兩個對象中任一個對象的hashCode方法都必須產生一樣的整數結果。若是返回false,那麼x和y的hashCode方法的返回值可能相等也可能不相等。反之,hashCode方法的返回值不相等必定能夠退出equals方法的返回值也不相等,而hashCode方法返回值相等,equals方法返回值有可能相等也可能不一樣。數組
java語言有四個類能夠對字符或字符串進行操做,它們分別是Character、String、StringBuffer和StringTokenizer,其中character用於對單個字符的操做,string用於字符串操做,屬於不可變類,StringBuffer也是用於字符串操做,不一樣之處是stringbuffer屬於可變類。緩存
string是不可變類,也就是說string對象一旦被建立,其值將不能被改變,而StringBuffer是可變類,當對象被建立後仍然能夠對其值進行修改。StringBuffer只能使用構造函數(StringBuffer s = new StringBuffer(「Hello」))的方式來初始化。安全
StringBuilder也是能夠被修改的字符串,它與StringBuffer相似,都是字符串緩衝區,但StringBuilder不是線程安全的。若是隻是在單線程中使用字符串緩衝區,那麼StringBuilder的效率會高些。所以在只有單線程訪問時可使用StringBuilder,當有多個線程訪問時,最好使用StringBuffer。由於StringBuffer必要時能夠對這些方法進行同步,因此任意特定實例上的全部操做就好像是以串行順序發生的,該順序與所涉及的每一個線程進行的方法調用順序一致。StringTokenizer是用來分割字符串的工具類。
在java語言的異常處理中,finally塊的做用是爲了保證不管出現什麼狀況,finally塊裏的代碼必定會被執行。因爲程序執行return就意味着結束對當前函數的調用並跳出這個函數體,所以任何語句要執行都只能在return以前執行(除非碰到exit函數),所以finally塊裏的代碼也是在return前執行的。此外,try-finally或者catch-finally中都有return,那麼finally塊中的return語句將會覆蓋別處的return語句,最終返回到調用者那裏的是finally中return的值。
異常是指程序運行時(非編譯時)所發生的非正常狀況或錯誤,當程序違反了語義規則時,JVM就會將出現的錯誤表示爲一個異常並拋出。這個異常能夠在catch程序塊中進行補貨,而後進行處理。而異常處理的目的則是爲了提升程序的安全性和魯棒性。
java語言把異常做爲對象來處理,並定義了一個基類做爲全部異常的父類。在java API中,已經定義了許多異常類,這些異常類分爲Error(錯誤)和Exception(異常)兩大類。
違反語義規則包括兩種狀況:一種是Java類庫內置的語義檢查例如當數組下標越界時會引起IndexOutOfBoundsException,當訪問null對象時,會引起NullPointerException;另外一種狀況是Java容許開發人員擴展這種語義檢查,開發人員能夠建立本身的異常類(全部異常都是Java.lang.Throwable的子類),並自由選擇在什麼時候用throw關鍵字拋出異常。
java提供了兩種錯誤的異常類,分別是錯誤和異常,且他們有共同的父類——Throwable。Error表示程序在運行期間出現了很是嚴重的錯誤,而且該錯誤是不可恢復的,因爲這屬於JVM層次的嚴重錯誤,所以這種錯誤是會致使程序終止執行的。Exception表示可恢復的異常,是編譯器能夠捕捉到的。它包含兩種類型:檢查異常和運行時異常。
檢查異常是在程序中最常碰到的異常。全部繼承自Exception而且不是運行時異常的異常都是檢查異常,好比最多見的IO異常和SQL異常。這種異常都發生在編譯階段,java編譯器強調程序去捕獲此類異常,即把可能會出現這些異常的代碼放到try塊中,把對異常處理的代碼放到catch塊中。這種異常一般在如下狀況中使用:異常的發生並不會致使程序出錯,進行處理後能夠繼續執行後續的操做,例如當鏈接數據庫失敗後能夠從新鏈接後進行後續操做。程序依賴於不可靠的外部條件,例如系統IO。
運行時異常不一樣於檢查異常,編譯器沒有強制對其進行補貨並處理。若是不對這些異常進行處理,當出現這種異常時,會由JVM來處理,例如NullPointerException異常,他就是運行時異常。最多見的還有類型轉換異常,數組越界異常,數組存儲異常,緩衝區溢出異常,算術異常等。出現運行時異常後,系統會把異常一致往上層拋出,知道遇處處理代碼爲止,若沒有處理塊,則拋到最上層;若是是多線程則用Thread.run()方法拋出,若是是單線程就用main()方法拋出。拋出以後,若是是單線程那麼這個線程也就退出了,若是是主程序拋出的異常,那麼整個程序也就退出啦。因此若是不對運行時異常進行處理,後果是很是嚴重的,一旦發生,要麼是線程終止,要麼是主程序終止。
在JAVA語言中,輸入和輸出都被稱爲抽象的流,流能夠被看作一組有序的字節集合,即數據在兩設備之間的傳輸。流的本質是數據傳輸,根據處理數據類型的不一樣,流能夠分爲兩大類:字節流和字符流。字節流以8bit爲單位,字符流以16bit爲單位。字節流和字符流之間最主要的區別是:字節流在處理輸入輸出時不會用到緩存,而字符流用到了緩存。
網絡上的兩個程序經過一個雙向的通訊鏈接來實現數據的交換,這個雙向鏈路的一端稱爲一個socket。socket也稱爲套接字,能夠用來實現不一樣虛擬機或不一樣計算機之間的通訊,在java語言中,socket能夠分爲兩種類型:面向鏈接的socket通訊協議(TCP)和麪向無鏈接的socket協議(UDP)。任何一個socket都是由IP地址和端口號惟一肯定的。
在非阻塞(Nonblocking)出現以前,java是經過傳統的socket來實現基本的網絡通訊功能的。
NIO經過selector、channel和buffer來實現非阻塞的IO操做。NIO非阻塞的實現主要採用了Reactor(反應器)設計模式,這個設計模式與Observer(觀察者)設計模式相似,只不過Observer設計模式只能處理一個事件源,而Reactor能夠用來處理多個事件源。
NIO在網絡編程中有着很是重要的做用,與傳統的socket方式相比,因爲NIO採用了非阻塞的方式,在處理大量併發請求時,使用NIO要比使用傳統socket效率高出不少。
java提供了兩種對象持久化的方式,分別是序列化和外部序列化。
一、序列化:在分佈式環境下,當進行遠程通訊時,不管是何種類型的數據,都會以二進制序列的方式在網絡上傳送。序列化是一種將對象以一連串的字節描述的過程,用於解決在對對象流進行讀寫操做時所引起的問題。序列化能夠將對象的狀態寫在流裏進行網絡傳輸,或者保存到文件、數據庫等系統裏,並在須要時把該流讀取出來從新構造一個相同的對象。全部要實現序列化的類都必須實現Serializable接口,Serializable接口位於java.lang包中,它裏面沒有包含任何方法。使用一個輸出流來構造一個ObjectOutputStream對象,緊接着,使用該對象的writeObject方法就能夠將obj對象寫出,要恢復時可使用其對應的輸入流。
因爲序列化的使用會影響系統的性能,所以若是不是必需要使用序列化,應儘量不要使用序列化,在如下狀況下使用:須要經過網絡來發送對象,或對象的狀態須要被持久化到數據庫或文件中。序列化能實現深複製,便可以複製引用的對象。
與序列化相對的是反序列化,它將流轉換爲對象。
二、外部序列化
外部序列化與序列化的主要區別在於序列化是內置的API,只須要實現Serializable接口,開發人員不須要編寫任何代碼就能夠實現對象的序列化,而是用外部序列化時,Externalizable接口中的讀寫方法必須有開發人員來實現。所以與實現Serializable接口的方法相比,使用Externalizable編寫程序的難讀更大,可是因爲把控制權交給了開發人員,在編程時有更多的靈活性,對須要持久化的那些屬性能夠進行控制,可能會提升性能。
java語言是一種具備動態性的解釋型語言,類只有被加載到JVM中後才能運行。當運行指定程序時,JVM會將編譯生成的.class文件按照需求和必定的規則加載到內存中,並組織成一個完整的java應用程序。這個過程是由類加載器完成的,具體來講就是由ClassLoader和它的子類來實現的。類加載器自己也是一個類,其實質是把類文件從硬盤讀到內存中。
類的加載方式分爲隱式加載和顯式加載兩種。隱式加載指的是程序在使用new等方式建立對象時會隱式的調用類的加載器把對應的類加載到JVM中。顯式加載指的是經過直接調用class.forName()方法來吧所需的類加載到JVM中。
垃圾回收在java語言中是一個很是重要的概念,它的主要做用是回收程序不在使用的內存。具體而言,垃圾回收期主要負責完成三項任務:分配內存、確保被引用對象的內存不被錯誤的回收以及回收不在被引用的對象的內存空間。
java Collection框架中包含了大量集合接口以及這些接口的實現類和操做它們的算法,具體而言,主要提供了List、queue、set、stack和map等數據結構。其中,List、queue、set、stack都繼承自collection接口。
ArrayList與Vector之間最大的區別是同步的使用,沒有一個ArrayList的方法是同步的,而vector的絕大多數方法是直接或間接同步的,因此Vector方法是線程安全的,ArrayList不是線程安全的。正是因爲Vector提供了線程安全的機制,其性能上也要略遜於ArrayList。
LinkedList是採用雙向列表實現的,對數據的索引須要從列表頭開始遍歷,所以用於隨機訪問則效率較低,可是插入元素時不須要對數據進行移動,所以插入效率較高。同時,LinkedList是非線程安全的容器。
HashMap是一個最經常使用的Map,他根據鍵的HashCode值存儲數據,根據鍵能夠直接獲取它的值,具備很快的訪問速度。因爲HashMap和Hashtable都採用了hash方法進行索引,所以兩者具備不少類似之處,它們的主要區別有:
1:HashMap是Hashtable的輕量級實現(非線程安全的實現),它們都完成了map接口,主要區別在於HashMap容許空鍵值(最多隻容許一條記錄的鍵爲空,不容許多條記錄的鍵爲空),而Hashtable不容許。
2:HashMap把Hashtable的contains方法去掉了,改爲了containsvalue和containsKey,由於contains方法容易讓人產生誤解。Hashtable繼承自directory類,而HashMap是java1.2引進的Map interface的一個實現。
3:Hashtable的方法是線程安全的,而HashMap不支持線程的同步,因此它不是線程安全的。在多個線程訪問Hashtable時,不須要開發人員對它進行同步,而對於HashMap,開發人員必須提供額外的同步機制。因此就效率而言,HashMap可能高於Hashtable。
4:Hashtable使用Enumeration,HashMap使用Iterator。
5:Hashtable和HashMap採用的hash/rehash算法都幾乎同樣,因此性能不會有很大差別。
6:在Hashtable中,hash數組默認大小是11,增長的方式是old*1+1,在HashMap中,hash數組的默認大小是16,並且必定是2的指數。
7:hash值的使用不一樣,Hashtable直接使用對象的hashcode。
因爲TreeMap實現了sortmap接口,可以把它保存的記錄根據鍵排序,所以,取出來的是排序後的鍵值對,若是須要按天然排序或自定義順序遍歷鍵,那麼treemap會更好LinkedHashMap是HashMap的一個子類,若是須要輸出的順序與輸入的順序相同,可使用它,他還能夠根據讀取順序來排列。
weakhashmap與HashMap相似,兩者的不一樣之處在於weakhashmap中key採用的是「弱引用」的方式,只要weakhashmap中的key再也不被外部引用,他就能夠被垃圾回收器回收。而HashMap中的key採用的是強引用的方式,當HashMap中的key沒有被外部引用時,只有在這個key從HashMap中刪除後才能夠被垃圾回收器回收。
Collection是一個集合接口。他提供了對集合對象進行基本操做的通用接口方法。實現該接口的類主要有List和set,該接口的設計目標是爲各類具體的集合提供最大化的統一的操做方式。
Collections是針對集合類的一個包裝類,它提供了一系列靜態方法以實現對各類集合的搜索、排序、線程安全化等操做,其中大多數方法都是用來處理線性表。Collections類不能實例化,如同一個工具類,服務於Collection框架。若在使用Collections的方法時,對應的Collection的對象爲null,則這些方法都會拋出NullPointerException。
一、使用多線程能夠減小程序運行的時間;二、與進程相比,線程的建立和切換開銷更小;三、多CPU或多核計算機自己就具備執行多線程的能力,若是使用單個線程,將沒法重複利用計算機資源,形成資源的巨大浪費;四、使用多線程能簡化程序的結構,使程序便於理解和維護。
一、繼承Thread類,重寫run()方法
二、實現Runnable()接口,並實現該接口的run()方法
三、實現Callable接口,重寫call()方法
一、synchronized關鍵字:在java語言中,每一個對象都有一個對象鎖與之相關聯,該鎖代表對象在任什麼時候候只容許被一個線程所擁有,當一個線程調用對象的一段synchronized代碼時,須要先得到這個鎖,而後去執行相應的代碼,執行結束後釋放鎖。synchronized關鍵字主要有兩種用法,synchronized方法和synchronized塊,此處該關鍵字還能夠做用於靜態方法、類或某個實例,但這都對程序的效率有很大的影響。
二、wait()方法和notify()方法:在synchronized代碼被執行期間線程能夠調用對象的wait()方法,釋放對象鎖,進入等待狀態,而且能夠調用notify()方法或notifyAll()方法通知正在等待的其餘進程。notify()方法用來喚醒一個線程並容許它得到鎖,notifyAll()方法喚醒全部等待這個對象的線程並容許它們去得到鎖。
三、Lock:
lock():以阻塞的方式獲取鎖,也就是說若是獲取到了鎖,當即返回;若是別的線程持有鎖,當前線程等待,直到獲取鎖後返回。
trylock():以非阻塞的方式獲取鎖。只是嘗試性的去獲取一下鎖,若是獲取到了鎖,當即返回true,不然當即返回false。
tryLock(long timeout,TimeUnit unit):若是獲取了鎖當即返回true,不然會等待參數給定的時間單元,在等待的過程當中,若是獲取了鎖,就返回true,若是等待超時返回false。
lockInterruptibly():若是獲取了鎖,當即返回;若是沒有獲取鎖,當前線程處於休眠狀態直到得到鎖,或者當前線程被別的線程中斷。
一、原理不一樣:sleep方法是Thread類的靜態方法,是線程用來控制自身流程的。而wait方法是Object類的方法,用於線程間的通訊,這個方法會使當前擁有該對象鎖的進程等待,直到其餘線程調用notify方法是才醒來,不過開發人員也能夠給他指定一個時間自動醒來。
二、對鎖的處理機制不一樣:因爲sleep方法的主要做用是讓線程暫停執行一段時間,時間一到自動恢復,不涉及線程間的通訊,所以調用sleep方法不會釋放鎖。而wait方法不一樣,調用它後,線程會釋放掉它所佔用的鎖,從而使線程所在對象中的其餘synchronized數據可被別的線程使用。
三、使用區域不一樣:因爲wait方法的特殊意義,它必須放在同步控制方法或者同步語句塊中使用,而sleep方法能夠在任何地方使用。
在java語言中,可使用stop和suspend方法來終止線程的執行。當用Thead.stop()來終止線程時,他會釋放已經鎖定的全部監視資源。若是當前任何一個受這些監視資源保護的對象處於一個不一致的狀態,其餘線程將會看到這個不一致的狀態,這可能會致使程序執行的不肯定性,而且這種問題很難被定位。調用suspend()方法很容易致使死鎖。因爲調用suspend()方法不會釋放鎖,這就會致使一個問題:若是用一個suspend掛起一個有鎖的線程,那麼在鎖恢復以前將不會被釋放。若是調用suspend方法,線程將試圖取得相同的鎖,程序就會發生死鎖。
java提供了兩種鎖機制來實現對某個共享資源的同步:synchronized和lock方法。其中,synchronized使用object對象自己的wait、notify和notifyAll調度機制,而lock能夠用condition進行線程之間的調度,完成synchronized實現的全部功能。
區別以下:
一、用法不同:在須要同步的對象中加入synchronized控制,synchronized既能夠加在方法上,也能夠加在特定代碼塊中,括號中表示須要鎖的對象。而lock須要顯式的指定起始位置和終止位置。synchronized是託管給jvm執行的,而lock的鎖定是經過代碼實現的,它有比synchronized更精確的線程語義。
二、性能不同:在JDK5中增長了一個Lock接口的實現類ReentrantLock。他不只擁有和synchronized相同的併發性和內存語義,還多了鎖投票、定時鎖、等候和中斷鎖等。它們的性能在不一樣的狀況下會有鎖不一樣:在資源競爭不是很激烈的狀況下,synchronized的性能要優於ReentrantLock,可是在資源競爭很激烈的狀況下,synchronized的性能降低的很是快,而ReentrantLock的性能基本保持不變。
三、鎖機制不同:synchronized得到鎖和釋放的方式都是在塊結構中,當獲取多個鎖時,必須以相反的順序釋放,而且是自動解鎖,不會由於出了異常而致使鎖沒有被釋放從而引起死鎖。而lock則須要開發人員手動去釋放,而且必須在finally塊中釋放,不然會引發死鎖問題的發生。此外,lock還提供了更強大的功能,它的tryLock方法能夠採用非阻塞的方式去獲取鎖。
java提供了兩種線程:守護線程和用戶線程。守護線程又被稱爲服務進程、精靈線程或後臺線程,是指在程序運行時在後臺提供一種通用服務的線程,這種線程並不屬於程序中不可或缺的一部分。通俗的講,任何一個守護線程都是整個JVM中全部非守護線程的保姆。
用戶線程和守護線程幾乎同樣,惟一的不一樣之處就在於若是用戶線程已經所有退出運行,只剩下守護線程存在了,JVM也就退出了。由於當全部非守護線程結束時,沒有了被守護者,守護線程也就沒工做可作了,也就沒有繼續運行程序的必要了,程序也就終止了,同時會殺死全部守護線程。
在java語言中,join方法的做用是讓調用該方法的線程在執行完run方法後再執行join方法後面的代碼。簡單來講就是將兩個線程合併,用於實現同步功能。
java數據庫鏈接(JDBC)用於在java程序中實現數據庫操做功能,他提供了執行SQL語句、訪問各類數據庫的方法,併爲各類不一樣數據庫提供統一的操做接口,java.sql包中包含了JDBC操做數據庫的全部類。經過JDBC訪問數據庫通常有以下幾個步驟:一、加載JDBC驅動器。將數據庫的JDBC驅動加載到classpath中,在基於JavaEE的web應用開發過程當中,一般要把目標數據庫產品的JDBC驅動複製到WEB_INF/lib下。二、加載JDBC驅動,並將其註冊到DriverManager中。通常使用反射Class.forName(String driveName)。三、創建數據庫鏈接,取得connection對象。通常經過DriverManager.getConnection(url,username,passwd)方法實現。四、創建Statement對象或是PreparedStatement對象。五、執行SQL語句。六、訪問結果集ResultSet對象。七、依次將ResultSet、Statement、PreparedStatement、Connection對象關閉,釋放掉所佔用資源。
一個事務是由一條或多條對數據庫操做的SQL語句所組成的一個不可分割的工做單元,只有當事務中的全部操做都正常執行完了,整個事務纔會被提交給數據庫。在JDBC中,通常是經過commit方法或rollback方法來結束事務的操做。其中commit方法表示完成對事務的提交,rollback表示完成事務回滾,多用於在處理事務的過程當中出現了異常的狀況,這兩種方法都位於java.sql.connection類中。通常而言,事務默認操做是自動提交,即操做成功後,系統將自動調用commit方法,不然將調用rollback方法。
固然在JDBC中也能夠經過調用setAutoCommit(false)方法來禁止自動提交,而後就能夠把多個數據庫操做的表達式做爲一個事務,在操做完成後調用commit方法實現總體提交,若是其中一個表達式操做失敗,就會拋出異常而不會調用commit方法。在這種狀況下就能夠在異常捕獲的代碼塊中調用rollback實現回滾。經過此種方法能夠保證對數據的屢次操做後,數據仍然保持一致性。
在java語言中,任何類只有在裝載到JVM上才能運行。Class.forName方法的做用就是把類加載到JVM上,他會返回一個與大有給定字符串名的類或接口相關聯的class對象,而且JVM會加載這個類,同時JVM會執行該類的靜態代碼段。
statement用來執行不帶參數的簡單SQL語句,並返回它所生成結果的對象,每次執行SQL語句時,數據庫都會編譯該SQL語句。
PreparedStatement表示預編譯的SQL語句的對象,用於執行帶參數的預編譯SQL語句。
CallableStatement則提供了用來調用數據庫中存儲過程的接口,若是有輸出參數要註冊,說明是輸出參數。
JDBC提供了getString、getInt和getData等方法從ResultSet中獲取數據,當查詢結果集中數據量較小時,不用考慮性能,使用這種方法徹底可以知足需求,可是當查詢結果集中的數據量很是大時則會拋出異常:OracleException未處理:...。而一般狀況下,使用getObject方法就能夠解決這個問題。
getString或getInt方法在被調用時,程序會一次性的把數據都放到內存中,而後經過調用ResultSet的next和getString等方法來獲取數據。當數據量大到內存中放不下的時候會拋出異常,而使用getObject方法就不會出現這種問題,由於數據不會一次性被讀取到內存中,每次調用時會直接從數據庫中去獲取數據,所以使用這種方法不會由於數據量過大而出錯。
在使用JDBC編程時,首先須要創建數據庫的鏈接才能完成對數據庫的訪問,因爲與數據庫的鏈接是很是重要的資源。JDBC鏈接池提供了JDBC鏈接定義和數目有限的鏈接,若是鏈接數量不夠,就須要長時間的等待。不正常關閉JDBC鏈接會致使等待回收無效的JDBC鏈接。只有正常的關閉和釋放JDBC鏈接,JDBC資源才能夠被快速的重用,從而使系統性能獲得改善。所以在編程時,必定要保證釋放不在使用的鏈接。
通常來說,在使用JDBC訪問數據庫時,createStatement和PreparedStatement最好放在循環外面,並且使用了這些statement後,須要及時關閉。最好是執行了一次executeQuery、executeUpdate等以後,若是不須要使用結果集(ResultSet)的數據,就立刻將statement關閉。由於每次執行conn.createStatement()和conn.prepareStatement,實際上都至關於在數據庫中打開一個cursor(遊標),若是把對這兩個方法的調用放在循環內,會一致不停的打開cursor。若是不能及時的關閉,會致使程序拋出異常。
java數據對象(java data object)是一個用於存取某種數據倉庫中的對象的標準化API,它使開發人員可以間接的訪問數據庫。
JDO是JDBC的一個補充,他提供了透明的對象存儲,所以對於開發人員來講,存儲數據對象徹底不須要額外的代碼(例如JDBC API的使用)。這些繁瑣的工做已經轉移到JDO產品提供商身上,使開發人員解脫出來,從而集中時間和精力在業務邏輯上。另外,相較於JDBC,JDO更加靈活,更通用,它提供了到任何數據底層的存儲功能。
Hibernate是JDBC的封裝,採用配置文件的形式將數據庫的鏈接參數寫到XML文件中,至於對數據庫的訪問仍是經過JDBC來完成的。
Hibernate是一個持久層框架,它將表的信息映射到XML文件中,再從XML文件映射到相應的持久化類中,這樣可使用Hibernate獨特的查詢語言了。