http://blog.csdn.net/pzxwhc/article/details/47129675 Tomcat執行流程html
http://www.importnew.com/17124.html Tomcat server.xml配置示例java
在Sun的Java Servlet規範中,對Java Web應用做了這樣定義:「Java Web應用由一組Servlet、HTML頁、類、以及其它能夠被綁定的資源構成。它能夠在各類供應商提供的實現Servlet規範的 Servlet容器 中運行。」程序員
Servlet容器爲JavaWeb應用提供運行時環境,它負責管理Servlet和JSP的生命週期,以及管理它們的共享數據。Servlet容器也稱爲JavaWeb應用容器,或者Servlet/JSP容器。web
目前最流行的Servlet容器軟件括:Tomcat,Resin,J2EE服務器(如Weblogic)中也提供了內置的Servlet容器。sql
Tomcat 是一個免費的開放源代碼的 Servlet 容器,它是 Apache 軟件基金會的一個頂級項目,由 Apache,Sun和其餘一些公司及我的共同開發而成。因爲有了 Sun 的參與和支持,最新的 Servlet 和 JSP 規範老是能在 Tomcat 中的到體現。數據庫
Tomcat是一個基於組件的服務器,他的構建組件都是能夠配置的,其中最外層的組件是Catalina Servlet容器,其餘組件必定要按照必定的格式要求配置在這個頂層的容器中。apache
<Server> 頂層類元素,可包含多個service編程
<Service> 頂層類元素,可包含一個Engine和多個Connector設計模式
<Connector/> 連接類容器,表明通訊接口數組
<Engine> 容器元素,爲Service處理客戶請求,含多個Host
<Host> 容器元素,爲Host處理客戶請求,含多個Context
<Context/> 容器元素,爲Web應用處理客戶請求
</Host>
</Engine>
</Service>
</Server>
1) Server
A Server element represents the entire Catalina servlet Container. (Singleton)單實例的。
2) Service
Service是一個集合。它由一個或者多個Connector組成,以及一個Engine,負責處理全部Connector所得到的客戶請求。
3) Connector 表示客戶端和service之間的鏈接
一個Connector將在某個指定端口上偵聽客戶請求,並將得到的請求交給Engine來處理,從Engine處得到迴應並返回客戶。
TOMCAT有兩個典型的Connector,一個直接偵聽來自browser的http請求,一個偵聽來自其它WebServer的請求。
Coyote Http/1.1 Connector 在端口8080處偵聽來自客戶browser的http請求。
Coyote JK2 Connector 在端口8009處偵聽來自其它WebServer(Apache)的servlet/jsp代理請求。
4) Engine 表示指定service中的請求處理機,接收和處理來自Connector的請求
Engine下能夠配置多個虛擬主機Virtual Host,每一個虛擬主機都有一個域名。當Engine得到一個請求時,它把該請求匹配到某個Host上,而後把該請求交給該Host來處理。Engine有一個默認虛擬主機,當請求沒法匹配到任何一個Host上的時候,將交給該默認Host來處理。
5) Host 表示一個虛擬主機
表明一個Virtual Host,虛擬主機,每一個虛擬主機和某個網絡域名Domain Name相匹配。每一個虛擬主機下均可以部署(deploy)一個或者多個Web App,每一個Web App對應於一個Context,有一個Context path
當Host得到一個請求時,將把該請求匹配到某個Context上,而後把該請求交給該Context來處理。匹配的方法是「最長匹配」,因此一個path==""的Context將成爲該Host的默認Context。全部沒法和其它Context的路徑名匹配的請求都將最終和該默認Context匹配。
6) Context 表示一個web應用程序
一個Context對應於一個Web Application,一個Web Application由一個或者多個Servlet組成。
一個Context對應於一個Web App,每一個Web App是由一個或者多個servlet組成的。
當一個Web App被初始化的時候,它將用本身的ClassLoader對象載入「部署配置文件web.xml」中定義的每一個servlet類。
它首先載入在$CATALINA_HOME/conf/web.xml中部署的servlet類
而後載入在本身的Web App根目錄下的WEB-INF/web.xml中部署的servlet類
web.xml文件有兩部分:servlet類定義和servlet映射定義
每一個被載入的servlet類都有一個名字,且被填入該Context的映射表(mapping table)中,和某種URL PATTERN對應
當該Context得到請求時,將查詢mapping table,找到被請求的servlet,並執行以得到請求迴應
分析一下全部的Context共享的web.xml文件,在其中定義的servlet被全部的Web App載入。
假設來自客戶的請求爲:
protocol :// hostname[:port] / path / [;parameters][?query]#fragment
http://localhost:8080/wsota/wsota_index.jsp
1) 請求被髮送到本機端口8080,被在那裏偵聽的Coyote HTTP/1.1 Connector得到
2) Connector把該請求交給它所在的Service的Engine來處理,並等待來自Engine的迴應
3) Engine得到請求localhost/wsota/wsota_index.jsp,匹配它所擁有的全部虛擬主機Host
4) Engine匹配到名爲localhost的Host(即便匹配不到也把請求交給該Host處理,由於該Host被定義爲該Engine的默認主機)
5) localhost Host得到請求/wsota/wsota_index.jsp,匹配它所擁有的全部Context
6) Host匹配到路徑爲/wsota的Context(若是匹配不到就把該請求交給路徑名爲""的Context去處理)
7) path="/wsota"的Context得到請求/wsota_index.jsp,在它的mapping table中尋找對應的servlet
8) Context匹配到URL PATTERN爲*.jsp的servlet,對應於JspServlet類
9) 構造HttpServletRequest對象和HttpServletResponse對象,做爲參數調用JspServlet的doGet或doPost方法
10)Context把執行完了以後的HttpServletResponse對象返回給Host
11)Host把HttpServletResponse對象返回給Engine
12)Engine把HttpServletResponse對象返回給Connector
13)Connector把HttpServletResponse對象返回給客戶browser
創建一個符合web應用目錄的程序結構MyWebContent。須要將類生成文件配置到WEB-INF的classes目錄下。
將MyWebContent複製到E:\apache-tomcat-7.0.34-noinstall\webapps目錄下,打開
http://localhost:8080/manager/html
打開
能夠看到
WEB-INF目錄下的classes和lib目錄均可以存放Java的類文件,在Servlet容器運行時,Web應用程序的類加載器將首先加載classes目錄下的,其次纔是lib目錄下的類。若是這兩個目錄下存在同名的類,起做用的將是classes目錄下的類。
例如:
例如:
例如:
例如:
例如:
第二種
返回結果集,經過把遊標做爲一個out參數來返回的。
Java調用
BLOB和CLOB都是大字段類型,BLOB是按二進制來存儲的,而CLOB是能夠直接存儲文字的。其實兩個是能夠互換的的,或者能夠直接用LOB字段代替這兩個。可是爲了更好的管理ORACLE數據庫,一般像圖片、文件、音樂等信息就用BLOB字段來存儲,先將文件轉爲二進制再存儲進去。而像文章或者是較長的文字,就用CLOB存儲,這樣對之後的查詢更新存儲等操做都提供很大的方便。
插入成功!
讀取而且複製
一、Object 的 equals 方法容易拋空指針異常,應使用常量或肯定有值的對象來調用 equals。
正例: "test".equals(object);
二、關於基本數據類型與包裝數據類型的使用標準以下:
全部的 POJO 類屬性必須使用包裝數據類型。
RPC 方法的返回值和參數必須使用包裝數據類型。
全部的局部變量推薦使用基本數據類型。
三、在集合迭代過程當中,不能直接調用集合的add,remove方法,會報java.util.ConcurrentModificationException異常。應該使用迭代器的移除方法。
ArrayList<String> list = new ArrayList<String>(Arrays.asList("a","b","c","d"));
// Iterator<String> iterator = list.iterator();
// while(iterator.hasNext()){
// if(iterator.next().equals("a")){
// iterator.remove();
// }
// }
for(String s : list){
if(s.equals("a")){
list.add("bbb");
}
}//java.util.ConcurrentModificationException
四、高併發時,同步調用應該去考量鎖的性能損耗。能用無鎖數據結構,就不要用鎖;能鎖區塊,就不要鎖整個方法體;能用對象鎖,就不要用類鎖。
五、併發修改同一記錄時,避免更新丟失,要麼在應用層加鎖,要麼在緩存加鎖,要麼在數據庫層使用樂觀鎖,使用 version 做爲更新依據。
> 說明: 若是每次訪問衝突機率小於 20%,推薦使用樂觀鎖,不然使用悲觀鎖。樂觀鎖的重試次數不得小於 3 次。
悲觀鎖(Pessimistic Lock),顧名思義,就是很悲觀,每次去拿數據的時候都認爲別人會修改,因此每次在拿數據的時候都會上鎖,這樣別人想拿這個數據就會block直到它拿到鎖。傳統的關係型數據庫裏邊就用到了不少這種鎖機制,好比行鎖,表鎖等,讀鎖,寫鎖等,都是在作操做以前先上鎖。
樂觀鎖(Optimistic Lock), 顧名思義,就是很樂觀,每次去拿數據的時候都認爲別人不會修改,因此不會上鎖,可是在更新的時候會判斷一下在此期間別人有沒有去更新這個數據,可使用版本號等機制。樂觀鎖適用於多讀的應用類型,這樣能夠提升吞吐量,像數據庫若是提供相似於write_condition機制的其實都是提供的樂觀鎖。
兩種鎖各有優缺點,不可認爲一種好於另外一種,像樂觀鎖適用於寫比較少的狀況下,即衝突真的不多發生的時候,這樣能夠省去了鎖的開銷,加大了系統的整個吞吐量。但若是常常產生衝突,上層應用會不斷的進行retry,這樣反卻是下降了性能,因此這種狀況下用悲觀鎖就比較合適。
六、若是使用要 if-else if-else 方式表達邏輯,【強制】請勿超過 3 層,超過請使用狀態設計模式。
http://blog.csdn.net/hguisu/article/details/7557252 狀態設計模式
七、避免用 Apache Beanutils 進行屬性的 copy。
> 說明: Apache BeanUtils 性能較差,可使用其餘方案好比 Spring BeanUtils, CglibBeanCopier。
八、後臺輸送給頁面的變量必須加$!{var}——中間的感嘆號。
> 說明: 若是 var=null 或者不存在,那麼${var}會直接顯示在頁面上。
1.一個項目就是一個工程。項目很是龐大,用package不適合劃分。最好是一個模塊對應一個工程。
能夠利用maven將一個項目拆分紅多個工程。
2.項目裏面的jar包都是手動複製和添加。這樣,同一個jar包會出如今多個項目中。
3.jar包須要本身下載。Jar包依賴關係。
一款服務於java平臺的自動化構建工具。Make、Ant、Maven、Gradle
運行時環境:就是一組jar包的引用。並無正真放入工做目錄。
編譯------------部署------------搭建
構建過程的各個環節
1.清理,將之前的字節碼class文件刪除
2.編譯,將java源程序編譯成class文件
3.測試,自動測試,調用junit程序
4.報告,測試結果
5.打包,web工程打war包,java工程打jar包
6.安裝,將打包文件複製到倉庫的指定位置
7.部署,將web動態工程生成的war包複製到severvlet容器的指定目錄下。
原工程與編譯結果對比圖
1.約定的目錄結構
2.POM,項目對象模型
3.座標,利用三個向量,在倉庫中定義一個Maven工程
GroupId: 公司或組織域名倒序+項目名
ArtifactId:模塊名,好比Hello
Version:版本,好比1.1.0,release可分離的穩定版,snapshot快照版迭代快
4.依賴,
Maven解析依賴信息時,會到本地倉庫中查找被依賴的jar包。
對於本身開發的maven工程,使用install命令來安裝,就能夠進入倉庫。
依賴範圍:<scope>compile</scope>
Compile 對主程序是否有效,對測試程序是否有效,是否參與打包。
Test
Provided
5.倉庫,本地倉庫和遠程倉庫。
6.聲明週期/插件/目標
7.繼承
8.聚合
①目錄結構
Hello 工程名
|---src 源碼
|---|---main 主程序
|---|---|---java 源碼
|---|---|---resources 框架和其餘配置文件
|---|---test 存放測試程序
|---|---|---java
|---|---|---resources
|---pom.xml Maven核心配置文件
②POM文件內容
Project Object Model項目對象模型
Document Object Model 文檔對象模型DOM
import static junit.framework.Assert.*; 靜態導入。類裏全部的靜態資源能夠直接用了。
assertEquals(「….」,results);斷言結果與給定字符串一致。
執行與構建(編譯、測試、打包)過程相關的命令,必須進入pom.xml文件所在目錄。
1. mvn clean: 清理
2. mvn compile: 編譯
3. mvn test-compile: 編譯測試程序
4. mvn test: 執行測試程序
5. mvn package: 打包
6. mvn install: 將本地jar包安裝到本地倉庫中
7. mvn site: 生成站點
先找本地倉庫,沒有相關jar包,就聯網下載。
各個構建環境執行的順序,順序執行。
定義了抽象聲明週期,具體由插件完成。
自動化構建的特色,不論要執行生命週期的哪個階段,都是從生命週期最初的位置開始執行。
能夠將目標看作調用功能的命令。
各個構的環境執行的順序,順序執行。
排除jar包
依賴原則:路徑最短優先。路徑相同時,先聲明優先。
傳遞依賴,非compile範圍內的不能傳遞依賴。
引用版本號:方便更改。
聚合:因爲有繼承後,須要先安裝父工程。聚合的做用就是一鍵安裝各個參與聚合的模塊。
好比:在Parent模塊中配置以下,
方法1(手動):
能夠將web引用,package先打包成war包。將war包複製到Tomcat安裝的webapps目錄下。
方法2(自動):
配置build標籤後,最好用cmd來運行deploy命令,不然須要手動關閉Tomcat。
方法1:命令
命令使用方法:首先進入到相應的pom.xml目錄中,而後執行如下命令:
mvn dependency:sources
mvn dependency:resolve -Dclassifier=javadoc
第一個命令是嘗試下載在pom.xml中依賴的文件的源代碼。
第二個命令是嘗試下載對應的javadocs
可是有可能一些文件沒有源代碼或者javadocs
方法2:配置文件
打開maven配置文件 setting.xml文件(.../.m2/settings.xml) 增長以下配置:
11. <activeProfiles>
13. </activeProfiles>
方法3:配置myeclipse 推薦使用
ORM:Object Relation Mapping 對象/關係映射
ORM 主要解決對象-關係的映射
ORM的思想:將關係數據庫中表中的記錄映射成爲對象,以對象的形式展示,程序員能夠把對數據庫的操做轉化爲對對象的操做。
ORM 採用元數據來描述對象-關係映射細節,元數據一般採用 XML 格式, 而且存放在專門的對象-關係映射文件中。(描述類、對象、屬性和表的行列對應關係)
元數據:描述數據的數據。
對象關係映射文件***.hbm.xml
1)hibernate配置文件hibernate.cfg.xml
2)建立對象-關係映射文件*.hbm.xml
編寫持久化類: POJO + 映射文件
獲取 Configuration 對象
獲取 SessionFactory 對象
獲取 Session,打開事務
用面向對象的方式操做數據庫
關閉事務,關閉 Session
3)Configuration 類負責管理 Hibernate 的配置信息。包括以下內容:
配置1:Hibernate 運行的底層信息:數據庫的URL、用戶名、密碼、JDBC驅動類,數據庫Dialect,數據庫鏈接池等(對應 hibernate.cfg.xml 文件)。
配置2:持久化類與數據表的映射關係(*.hbm.xml 文件)
4)SessionFactory針對單個數據庫映射關係通過編譯後的內存鏡像,是線程安全的。 SessionFactory 對象一旦構造完畢,即被賦予特定的配置信息。SessionFactory是生成Session的工廠。構造 SessionFactory 很消耗資源,通常狀況下一個應用中只初始化一個 SessionFactory 對象。
5)Session 是應用程序與數據庫之間交互操做的一個單線程對象,是 Hibernate 運做的中心,全部持久化對象必須在 session 的管理下才能夠進行持久化操做。此對象的生命週期很短。Session 對象有一個一級緩存,顯式執行 flush 以前,全部的持久層操做的數據都緩存在 session 對象處。至關於 JDBC 中的 Connection。
取得持久化對象的方法: get() load()
持久化對象都得保存,更新和刪除:save(),update(),saveOrUpdate(),delete()
開啓事務: beginTransaction().
管理 Session 的方法:isOpen(),flush(), clear(), evict(), close()等
注意紅色部分,是以斜槓隔斷。
Session 接口是 Hibernate 嚮應用程序提供的操縱數據庫的最主要的接口,它提供了基本的保存,更新, 刪除和加載 Java 對象的方法.
Session 具備一個緩存,位於緩存中的對象稱爲持久化對象,它和數據庫中的相關記錄對應。Session 可以在某些時間點,按照緩存中對象的變化來執行相關的 SQL 語句,來同步更新數據庫,這一過程被稱爲刷新緩存(flush)。
站在持久化的角度,Hibernate 把對象分爲 4 種狀態:臨時狀態,持久化狀態,遊離狀態,刪除狀態。 Session 的特定方法能使對象從一個狀態轉換到另外一個狀態。
在 Session 接口的實現中包含一系列的 Java 集合,這些 Java 集合構成了 Session 緩存。只要 Session 實例沒有結束生命週期,且沒有清理緩存,則存放在它緩存中的對象也不會結束生命週期。
Session 緩存可減小 Hibernate 應用程序訪問數據庫的頻率。
Flush使得數據表中的記錄和session緩存中的狀態保持一致,可能會發送對應的SQL語句。
在Transaction的commit()方法中先調用flush方法,再commit。
Flush()方法可能會發送sql語句,可是不會提交事務,也就是數據表的記錄不會改變。
3. 注意: 在未提交事務或顯式的調用 session.flush() 方法以前,也有可能會進行 flush() 操做。
* 1). 執行 HQL 或 QBC 查詢,會先進行 flush() 操做,以獲得數據表的最新的記錄
* 2). 若記錄的 ID 是由底層數據庫使用自增的方式生成的,則在調用 save() 方法時,就會當即發送 INSERT 語句。
* 由於 save 方法後,必須保證對象的 ID 是存在的!
Refresh會強制發送 SELECT 語句,以使 Session 緩存中對象的狀態和數據表中對應的記錄保持一致!
站在持久化的角度,Hibernate 把對象分爲 4 種狀態:Transient,Persist,Detached,Removed。Session 的特定方法能使對象從一個狀態轉換到另外一個狀態。
臨時對象(Transient):
在使用代理主鍵的狀況下,OID 一般爲 null
不處於 Session 的緩存中
在數據庫中沒有對應的記錄
持久化對象(也叫」託管」)(Persist):
OID 不爲 null
位於 Session 緩存中
對應性:若在數據庫中已經有和其對應的記錄,持久化對象和數據庫中的相關記錄對應
同步性:Session 在 flush 緩存時,會根據持久化對象的屬性變化,來同步更新數據庫
惟一性:在同一個 Session 實例的緩存中,數據庫表中的每條記錄只對應惟一的持久化對象。若是一個session的數據庫記錄有兩個對象,那麼以哪一個更新呢?因此是隻有一個。
遊離對象(也叫」脫管」) (Detached):相似於公司中員工請假了,不受公司管理,可是還屬於公司
OID 不爲 null
再也不處於 Session 緩存中
通常狀況需下,遊離對象是由持久化對象轉變過來的,所以在數據庫中可能還存在與它對應的記錄
刪除對象(Removed)
在數據庫中沒有和其 OID 對應的記錄
再也不處於 Session 緩存中
通常狀況下,應用程序不應再使用被刪除的對象
1. save() 方法
* 1). 使一個臨時對象變爲持久化對象
* 2). 爲對象分配 ID.
* 3). 在 flush 緩存時會發送一條 INSERT 語句.
* 4). 在 save 方法以前的 id 是無效的
* 5). 持久化對象的 ID 是不能被修改的!
2. persist(): 也會執行 INSERT 操做
* 和 save() 的區別 :
* 在調用 persist 方法以前,若對象已經有 id 了,則不會執行 INSERT,而拋出異常
3. get VS load:
* 1. 執行 get 方法:會當即加載對象
* 執行 load 方法:若不使用該對象,則不會當即執行查詢操做,而返回一個代理對象
* get 是 當即檢索,load 是延遲檢索
* 2. load 方法可能會拋出 LazyInitializationException 異常:在須要初始化
* 代理對象以前已經關閉了 Session
* 3. 若數據表中沒有對應的記錄,Session 也沒有被關閉
* get 返回 null
* load 若不使用該對象的任何屬性,沒問題。若須要初始化了,拋出異常
4. update:
* 1. 若更新一個持久化對象,不須要顯示的調用 update 方法。由於在調用 Transaction的 commit() 方法時,會先執行 session 的 flush 方法
* 2. 更新一個遊離對象,須要顯式的調用 session 的 update 方法。能夠把一個遊離對象變爲持久化對象
* 須要注意的:
* 1. 不管要更新的遊離對象和數據表的記錄是否一致,都會發送 UPDATE 語句
* 如何能讓 update 方法再也不盲目的出發 update 語句呢 ? 在 .hbm.xml 文件的 class 節點設置
* select-before-update=true (默認爲 false)。但一般不須要設置該屬性
* 2. 若數據表中沒有對應的記錄,但還調用了 update 方法,會拋出異常
* 3. 當 update() 方法關聯一個遊離對象時
* 若是在 Session 的緩存中已經存在相同 OID 的持久化對象,會拋出異常。由於在 Session 緩存中
* 不能有兩個 OID 相同的對象!
5. saveOrUpdate:同時包含了save和update方法
6.delete: 執行刪除操做。只要 OID 和數據表中一條記錄對應,就會準備執行 delete 操做
* 若 OID 在數據表中沒有對應的記錄,則拋出異常
* 能夠經過設置 hibernate 配置文件 hibernate.use_identifier_rollback 爲 true
* 使刪除對象後,把其 OID 置爲 null
能夠在刪除方法調用後,將OID當即置爲null
7.evict: 從 session 緩存中把指定的持久化對象移除
Work 接口: 直接經過 JDBC API 來訪問數據庫的操做。
Session 的 doWork(Work) 方法用於執行 Work 對象指定的操做,即調用 Work 對象的 execute() 方法。Session 會把當前使用的數據庫鏈接傳遞給 execute() 方法
Hibernate 與數據庫中的觸發器協同工做時,會形成兩類問題:
1)觸發器使 Session 的緩存中的持久化對象與數據庫中對應的數據不一致:觸發器運行在數據庫中,它執行的操做對 Session 是透明的。
即,session操做致使觸發器更改了數據庫內容,須要同步,要當即調用flush和refresh方法
2)Session 的 update() 方法盲目地激發觸發器:不管遊離對象的屬性是否發生變化,都會執行 update 語句,而 update 語句會激發數據庫中相應的觸發器。
所以,須要在映射文件的<class>元素中設置select-before-update屬性:當 Session 的 update 或 saveOrUpdate() 方法更新一個遊離對象時,會先執行 Select 語句,得到當前遊離對象在數據庫中的最新數據,只有在不一致的狀況下才會執行 update 語句。
hibernate-mapping.xml
類層次:class
主鍵:id
基本類型:property
實體引用類: many-to-one | one-to-one
集合:set | list | map | array
one-to-many
many-to-many
子類:subclass | joined-subclass
其它:component | any 等
查詢語句:query(用來放置查詢語句,便於對數據庫查詢的統一管理和優化)
每一個Hibernate-mapping中能夠同時定義多個類。但更推薦爲每一個類都建立一個單獨的映射文件
1)class標籤中,dynamic-update:若設置爲 true,表示當更新一個對象時,會動態生成 update 語句,update 語句中僅包含全部取值須要更新的字段。默認值爲 false。
2)類型映射
在 Java 中,表明時間和日期的類型包括: java.util.Date 和 java.util.Calendar. 此外,在 JDBC API 中還提供了 3 個擴展了 java.util.Date 類的子類: java.sql.Date,java.sql.Time 和 java.sql.Timestamp,這三個類分別和標準 SQL 類型中的 DATE,TIME 和 TIMESTAMP 類型對應。
因此在持久化類中,應設置爲java.util.Date類型,這樣就能夠接收數據庫全部類型。
如何映射:type設置爲date、time、timestamp三類Hibernate類型
在 Java 中, java.lang.String 可用於表示長字符串(長度超過 255),字節數組 byte[] 可用於存放圖片或文件的二進制數據。此外,在 JDBC API 中還提供了 java.sql.Clob 和 java.sql.Blob 類型,它們分別和標準 SQL 中的 CLOB 和 BLOB 類型對應。CLOB 表示字符串大對象(Character Large Object),BLOB表示二進制對象(Binary Large Object)。
問題來源:創建域模型和關係數據模型有着不一樣的出發點:
域模型:由程序代碼組成,經過細化持久化類的粒度可提升代碼的可重用性,簡化編程。
類,越多越細化越好
在沒有數據冗餘的狀況下,應該儘量減小表的數目,簡化表之間的參照關係,以便提升數據的訪問速度。
數據表,越少越好
Hibernate 把持久化類的屬性分爲兩種:
值(value)類型:沒有 OID,不能被單獨持久化,生命週期依賴於所屬的持久化類的對象的生命週期
實體(entity)類型:有 OID,能夠被單獨持久化,有獨立的生命週期
顯然沒法直接用 property 映射 pay 屬性
Hibernate 使用 <component> 元素來映射組成關係,該元素表名 pay 屬性是 Worker 類一個組成部分,在 Hibernate 中稱之爲組件。
在領域模型中,類與類之間最廣泛的關係就是關聯關係。
在 UML 中,關聯是有方向的。以 Customer 和 Order 爲例: 一個用戶能發出多個訂單,而一個訂單隻能屬於一個客戶。從 Order 到 Customer 的關聯是多對一關聯;而從 Customer 到 Order 是一對多關聯。
單向關聯
n-1:order裏面有一個對customer的引用
1-n:customer中有order的集合的引用
雙向關聯
1)單向n-1
單向 n-1 關聯只需從 n 的一端能夠訪問 1 的一端。
域模型:從 Order 到 Customer 的多對一單向關聯須要在Order 類中定義一個 Customer 屬性,而在 Customer 類中無需定義存放 Order 對象的集合屬性。
關係數據模型:ORDERS 表中的 CUSTOMER_ID 參照 CUSTOMER 表的主鍵
在order.hbm.xml中配置
Session.save()保存的時候須要先保存一customer的一端。
查詢多的一端order的時候,進行了延遲加載,沒有查出一的customer一端。若先關閉了session再使用customer會報懶加載異常LazyInitalizationException。
在不設定級聯關係下,刪除一的customer一端會報錯。
2)雙向n-1
雙向 1-n 與 雙向 n-1 是徹底相同的兩種情形
雙向 1-n 須要在 1 的一端能夠訪問 n 的一端,反之依然.
域模型:從 Order 到 Customer 的多對一雙向關聯須要在Order 類中定義一個 Customer 屬性,而在 Customer 類中需定義存放 Order 對象的集合屬性。
關係數據模型:ORDERS 表中的 CUSTOMER_ID 參照 CUSTOMER 表的主鍵。和上面的數據表設計同樣。
在java,Customer類中這樣設置:
在Customer.hbm.xml中這樣配置:
3)1-1
1對1關聯關係,利用了多對一關聯關係來創建。域模型:一個部門只能有一個領導,一個領導也只能管理一個部門。
關係數據庫模型,有兩種:
1、按照外鍵映射,利用多對一,可是多的那一端須要加上unique關鍵字。即在配置many-to-one那一端會有一個外鍵生成。
配置以下:
Department.hbm.xml
Manager.hbm.xml,注意須要property-ref屬性指定出了所關聯實體主鍵之外的關聯字段!!!左外鏈接
2、按照主鍵映射
基於主鍵的映射策略:指一端的主鍵生成器使用 foreign 策略,代表根據」對方」的主鍵來生成本身的主鍵,本身並不能獨立生成主鍵。 <param> 子元素指定使用當前持久化類的哪一個屬性做爲 「對方」。
Department.hbm.xml中配置。注意是當前持久化類的哪個屬性做爲主鍵配置!!!
在Manager.hbm.xml中配置
3)單向多對多
域模型:商品,列表。一個商品能夠屬於多個列表類,一個列表類也能夠有多個商品。
關係數據模型:
在Category.hbm.xml中配置
在Item.hbm.xml中配置
子類和父類公用一張數據表。父類中沒有的字段值爲空。有一列爲TYPE辨別者列,做爲類型區分。
對於面向對象的程序設計語言而言,繼承和多態是兩個最基本的概念。Hibernate 的繼承映射能夠理解持久化類之間的繼承關係。例如:人和學生之間的關係。學生繼承了人,能夠認爲學生是一個特殊的人,若是對人進行查詢,學生的實例也將被獲得。
1)使用 subclass 進行映射:將域模型中的每個實體對象映射到一個獨立的表中,也就是說不用在關係數據模型中考慮域模型中的繼承關係和多態。
只用配置父類Person.hbm.xml文件
2)使用 joined-subclass 進行映射: 對於繼承關係中的子類使用同一個表,這就須要在數據庫表中增長額外的區分子類類型的字段。
3)使用 union-subclass 進行映射:域模型中的每一個類映射到一個表,經過關係數據模型中的外鍵來描述表之間的繼承關係。這也就至關於按照域模型的結構來創建數據庫中的表,並經過外鍵來創建表之間的繼承關係。
導航對象圖檢索方式:根據已經加載的對象導航到其餘對象。好比,customer獲得order
OID 檢索方式:按照對象的 OID 來檢索對象,get,lod
HQL 檢索方式:使用面向對象的 HQL 查詢語言
QBC 檢索方式:使用 QBC(Query By Criteria) API 來檢索對象。這種 API 封裝了基於字符串形式的查詢語句,提供了更加面向對象的查詢接口。
本地 SQL 檢索方式:使用本地數據庫的 SQL 查詢語句。
1)HQL
HQL(Hibernate Query Language) 是面向對象的查詢語言,它和 SQL 查詢語言有些類似。在 Hibernate 提供的各類檢索方式中,HQL 是使用最廣的一種檢索方式。它有以下功能:
在查詢語句中設定各類查詢條件
支持投影查詢,即僅檢索出對象的部分屬性
支持分頁查詢
支持鏈接查詢
支持分組查詢,容許使用 HAVING 和 GROUP BY 關鍵字
提供內置彙集函數,如 sum(),min() 和 max()
支持子查詢
支持動態綁定參數
可以調用 用戶定義的 SQL 函數或標準的 SQL 函數
2)QBC 查詢就是經過使用 Hibernate 提供的 Query By Criteria API 來查詢對象,這種 API 封裝了 SQL 語句的動態拼裝,對查詢提供了更加面向對象的功能接口
3)本地SQL查詢來完善HQL不能涵蓋全部的查詢特性