A)<set> B)<one-to-many> C)<many-to-one> D)<property>
cascade屬性值描述
臨時狀態: 當new一個實體對象後,這個對象處於臨時狀態 ,即這個對象只是一個保存臨時數據的內存區域,如果沒有變量引用這個對象,則會被jre垃圾回收機制回收。這個對象所保存的數據與數據庫沒有任何關係,除非通過Session的save或者SaveOrUpdate把臨時對象與數據庫關聯,並把數據插入或者更新到數據庫,這個對象才轉換爲持久對象。
例如:Emp e=new Emp(); //創建臨時對象
e.setEmpno((long) 8888);
e.setEName("mike");
...
EmpDAO d=new EmpDAO();
d.save(e); //持久化
...
持久狀態:持久化對象的實例在數據庫中有對應的記錄,並擁有一個持久化表示(ID)。對持久化對象進行delete操作後,數據庫中對應的記錄將被刪除,那麼持久化對象與數據庫記錄不再存在對應關係,持久化對象變成臨時狀態。
持久化對象被修改變更後,不會馬上同步到數據庫,知道數據庫事務提交。在同步之前,持久化對象是髒的(Dirty)。
例如:
Emp e=new Emp(); //創建了臨時的對象
EmpDAO edao= new empDAO();
e=edao.findbyEmpno((long) 7786); //使對象與數據庫記錄對應,從而持久化
e.setEname("新的名字"); //修改了持久化對象,使之處於 Dirty
......
edao.saveorupdate(e); //保存,但是仍然 Dirty
tran.commit(); //提交,實現與數據庫同步,不再Dirty
......
遊離狀態:當Session進行了Close、Clear或者evict後,持久化對象雖然擁有持久化標識符和與數據庫對應記錄一致的值,但是因爲會話已經消失,對象不在持久化管理之內,所以處於遊離狀態(也叫:脫管狀態)。遊離狀態的對象與臨時狀態對象是十分相似的,只是它還含有持久化標識。
其中,持久化狀態的對象,簡稱爲:PO
而臨時狀態和遊離狀態的對象,簡稱爲: VO
它指的是對數據被外界修改持保守態度。假定任何時刻存取數據時,都可能有另一個客戶也正在存取同一筆數據,爲了保持數據被操作的一致性,於是對數據採取了數據庫層次的鎖定狀態,依靠數據庫提供的鎖機制來實現。
基於jdbc實現的數據庫加鎖如下:
select * from account where name="Erica" for update
在更新的過程中,數據庫處於加鎖狀態,任何其他的針對本條數據的操作都將被延遲。本次事務提交後解鎖。
而hibernate悲觀鎖的具體實現如下:
String sql="查詢語句";
Query query=session.createQuery(sql);
query.setLockMode("對象",LockModel.UPGRADE);
說到這裏,就提到了hibernate的加鎖模式:
LockMode.NONE:無鎖機制。
LockMode.WRITE:Hibernate在Insert和Update記錄的時候會自動獲取。
LockMode.READ:Hibernate在讀取記錄的時候會自動獲取。
這三種加鎖模式是供hibernate內部使用的,與數據庫加鎖無關:
LockMode.UPGRADE:利用數據庫的for update字句加鎖。
在這裏我們要注意的是:只有在查詢開始之前(也就是hiernate生成sql語句之前)加鎖,纔會真正通過數據庫的鎖機制加鎖處理。否則,數據已經通過不包含for updata子句的sql語句加載進來,所謂的數據庫加鎖也就無從談起。
但是,從系統的性能上來考慮,對於單機或小系統而言,這並不成問題,然而如果是在網絡上的系統,同時間會有許多聯機,假設有數以百計或上千甚至更多的併發訪問出現,我們該怎麼辦?如果等到數據庫解鎖我們再進行下面的操作,我們浪費的資源是多少?--這也就導致了樂觀鎖的產生。
2.樂觀鎖
樂觀鎖定(optimistic locking)則樂觀的認爲資料的存取很少發生同時存取的問題,因而不作數據庫層次上的鎖定,爲了維護正確的數據,樂觀鎖定採用應用程序上的邏輯實現版本控制的方法。
例如若有兩個客戶端,A客戶先讀取了賬戶餘額100元,之後B客戶也讀取了賬戶餘額100元的數據,A客戶提取了50元,對數據庫作了變更,此時數據庫中的餘額爲50元,B客戶也要提取30元,根據其所取得的資料,100-30將爲70餘額,若此時再對數據庫進行變更,最後的餘額就會不正確。
在不實行悲觀鎖定策略的情況下,數據不一致的情況一但發生,有幾個解決的方法,一種是先更新爲主,一種是後更新的爲主,比較複雜的就是檢查發生變動的數據來實現,或是檢查所有屬性來實現樂觀鎖定。
Hibernate 中透過版本號檢查來實現後更新爲主,這也是Hibernate所推薦的方式,在數據庫中加入一個VERSON欄記錄,在讀取數據時連同版本號一同讀取,並在更新數據時遞增版本號,然後比對版本號與數據庫中的版本號,如果大於數據庫中的版本號則予以更新,否則就回報錯誤。
以剛纔的例子,A客戶讀取賬戶餘額1000元,並連帶讀取版本號爲5的話,B客戶此時也讀取賬號餘額1000元,版本號也爲5,A客戶在領款後賬戶餘額爲500,此時將版本號加1,版本號目前爲6,而數據庫中版本號爲5,所以予以更新,更新數據庫後,數據庫此時餘額爲500,版本號爲6,B客戶領款後要變更數據庫,其版本號爲5,但是數據庫的版本號爲6,此時不予更新,B客戶數據重新讀取數據庫中新的數據並重新進行業務流程才變更數據庫。
以Hibernate實現版本號控制鎖定的話,我們的對象中增加一個version屬性,例如:
view plaincopy to clipboardprint?
public class Account {
private int version;
....
public void setVersion(int version) {
this.version = version;
}
public int getVersion() {
return version;
}
....
}
public class Account {
private int version;
....
public void setVersion(int version) {
this.version = version;
}
public int getVersion() {
return version;
}
....
}
二,簡答題
Hibernate工作原理及爲什麼要用?
答:
原理:
1.讀取並解析配置文件
2.讀取並解析映射信息,通過SessionFactory創建Session
3.打開Sesssion
4.創建事務Transation
5.持久化操作
6.提交事務
7.關閉Session
爲什麼要用:
1. 對JDBC訪問數據庫的代碼做了封裝,大大簡化了數據訪問層繁瑣的重複性代碼。
2. Hibernate是一個基於JDBC的主流持久化框架,是一個優秀的ORM實現。他很大程度的簡化DAO層的編碼工作
3. hibernate使用Java反射機制,而不是字節碼增強程序來實現透明性。
4. hibernate的性能非常好,因爲它是個輕量級框架。映射的靈活性很出色。它支持各種關係數據庫,從一對一到多對多的各種複雜關係。
1. Hibernate2延遲加載實現:a)實體對象 b)集合(Collection)
2. Hibernate3 提供了屬性的延遲加載功能
當Hibernate在查詢數據的時候,數據並沒有存在與內存中,當程序真正對數據的操作時,對象才存在與內存中,就實現了延遲加載,他節省了服務器的內存開銷,從而提高了服務器的性能。
3.hibernate 進行多表查詢每個表中各取幾個字段,也就是說查詢出來的結果集沒有一個實體類與之對應如何解決?
可以將查詢返回一個DynaBean比如
List<DynaBean>list=statement.executeSQLQuery("select a.aa,b.bb from a,b");
for(DynaBean db:list){
String a1= (String)db.get("aa");
Stringb1= (String)db.get("bb");
}
Or
List list=query.list();
Iterator it=list.itreator();
While(it.hasNext()){
Object[]obj=(Object[])it.next();
Stringal=(String)obj[0];
}
4.Hibernate中怎樣實現類之間的關係?(如:一對多、多對多的關係)
答:
類與類之間的關係主要體現在表與表之間的關係進行操作,它們都是對對象進行操作,我們程序中把所有的表與類都映射在一起,它們通過配置文件中的many-to-one、one-to-many、many-to-many
5. 說下Hibernate的緩存機制
答:
hibernate中存在兩種緩存,即內置緩存和外只緩存。
1. 內部緩存存在Hibernate中又叫一級緩存,屬於應用事物級緩存
2. 二級緩存:
a) 應用及緩存
b) 分佈式緩存
條件:數據不會被第三方修改、數據大小在可接受範圍、數據更新頻率低、同一數據被系統頻繁使用、非 關鍵數據
c) 第三方緩存的實現
6. Hibernate的查詢方式
Sql、Criteria,object comptosition
Hql:
1、 屬性查詢
2、 參數查詢、命名參數查詢
3、 關聯查詢
4、 分頁查詢
5、 統計函數
7.hibernate 中的 update() 和 saveOrUpdate() 的區別, session 的 load() 和 get() 的區別。
答:
Update 更新的是已有的數據,如果沒有則會報錯。 SaveOrUpdate 則可以將數據庫中沒有數據進行保存,有的數據進行修改
Load 和 get 都是查詢數據對象。 Load 首先會從緩存中加載,如果緩存中沒有該數據,則去數據庫中查找, get 會直接去數據庫加載。當數據的查詢波動比較小時,可以使用 load 來優化數據操作,反之則會帶來更大的負擔
從這個可以將一些關於iterate和list()來優化考官對自己的認可之類的
8.Session清理緩存的三種模式
清理緩存的模式
Session查詢方法
Session的Commit方法
Session的Flush方法
9. Hibernate的主鍵生成機制
答:
在項目中,通常使用UUID(Universally Unique Identifier 唯一標示符)作爲主鍵.
常用的組建有:
1) Assigned
主鍵由外部程序負責生成,無需Hibernate參與。
2) hilo
通過hi/lo 算法實現的主鍵生成機制,需要額外的數據庫表保存主鍵生成歷史狀態。
主鍵按數值順序遞增。此方式的實現機制爲在當前應用實例中維持一個變量,以保存着當前的最大值,之後每次需要生成主鍵的時候將此值加1作爲主鍵。
這種方式可能產生的問題是:如果當前有多個實例訪問同一個數據庫,那麼由於各個實例各自維護主鍵狀態,不同實例可能生成同樣的主鍵,從而造成主鍵重複異常。因此,如果同一數據庫有多個實例訪問,此方式必須避免使用。
5) identity
採用數據庫提供的主鍵生成機制。如DB2、SQL Server、MySQL中的主鍵生成機制。
6) sequence
採用數據庫提供的sequence 機制生成主鍵。如Oralce 中的Sequence。